*****************************************************************************
**                                                                         **
** Engine: Toccata Amplifier											   **
**                                                                         **
** Project: Eagleplayer 2.04                                               **
** Authors: Jan Blumenthal & Henryk Richter                                **
** Start  : 1993/01/09                                                     **
** $Header$                                                                **
**                                                                         **
*****************************************************************************
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program (See the included file COPYING);
** if not, write to the Free Software Foundation, Inc.,
** 675 Mass Ave, Cambridge, MA 02139, USA.
**
***************************************************************************** 

;26.11. Problem beim Abspielen von 44.1 kHz Samples behoben
;8.1.99 CopyBufstereo schneller
	;
	;
	incdir	include:
	include	exec/exec_lib.i
	include	exec/execbase.i
	include	exec/libraries.i
	include	exec/lists.i
	include	exec/memory.i
	include	exec/types.i
 	include	intuition/intuition.i
	include	intuition/intuition_LIB.i
	include	graphics/graphics_lib.i
	include	libraries/gadtools.i
	include	libraries/gadtools_lib.i
	include	dos/dos_lib.i
	include	libraries/dos.i
	include	misc/eagleplayer.i
	include	misc/eagleplayerengine.i
	include	misc/BuggsMacros.i

	include	misc/Toccata.i
	include	misc/Toccata_lib.i

	;
	section	0,code_p
	;
ver		macro
		dc.b	"0.34"
		endm
StructVer	macro
		dc.w	0,34
		endm
date		macro
		dc.b	"20-May-98"
		endm
StructDate	macro
		dc.b	20,5
		dc.w	1998
		endm

userprogram	=	1
debug	 	=	0
test		=	0		;topaz nehmen ?
secondInt	=	0
speedtest	=	0		;Farbige Anzeige der benötigten Rasterzeit der Mixroutine
SamLEN		=	256		;Anzahl der pro Kanal auf einmal zu mixenden
					;Bytes/2 !!, sprich bei einem Wert von 64
					;werden 128 Bytes zu 128 Ausgangswörtern zusammengemixt
RawSize		=	2048

testfreqlist	=	0		;nur zum Testen !!

Benchmark	=	0	;Benchmark = 1 => Vergleich zwischen alter wortweiser und neuer 
				;                 langwortweiser CopyBuffer Routine
BenchMark2	=	0
V37Gadtools	=	0	;Test für Kick2.0 Kompatibilität durch Gadtools13.library

NumChipBuffers	=	4	;16	;Anzahl der Puffer im Chipram (wg. FFT Analyzer)

	ifeq	SecondInt
	if	[SamLEN*8]<>RawSize

		He Du ! Denk an die Samplelänge !

	endc
	endc

;----------------------- Noteplayer-spezifische Infos --------------------

Project0Width = 309		;Windowbreite (default bei Topaz 8)
Project0Height = 158
Project0Left = 41
Project0Top = 45
ZoomWidth = 200

BevelHohe		= 1
BevelBreite		= 2
ListviewBorder		= 4		*Höhe des ListviewRandes (oben+unten)
MinListViewWidth	= 40		*Min Width der Listviews
MinGadgetWidth		= 15		*Min. Breite von Gadgets
MinTextGadgetXOffset	= 2		*Abstand des Textes im Gadget vom
					*Bevelrand
MinTextGadgetYOffset	= 2		*Abstand des Textes im Gadget vom
					*Bevelrand
GadgetXAbstand		= 4		*Abstand der Gadgets untereinander
					*sowie vom linken Rand
GadgetYAbstand		= 4		*Abstand der Gadgets untereinander
					*sowie vom oberen & unteren Rand
AboveAbstand		= 7		*Abstand, wenn Text überm ListView

GD_LISTVIEW                            EQU    0
GD_Samplefreq                          EQU    1
GD_MixingSlider                        EQU    2
GD_VBoost                              EQU    3
GD_Voices                              EQU    4
GD_NumVBoost                           EQU    5
GD_Playmode                            EQU    6
GD_Surlevel                            EQU    7

Project0_CNT    EQU    8


 structure	my_liststruct,0
	struct	ML_Node,ln_size
	struct	ML_Nodename,40
	Label	ML_Sizeof

ASLoopF_BackLooping	EQU	0
ASLoopF_Looping		EQU	1
ASLoopB_BackLooping	EQU	1<<ASLoopF_BackLooping
ASLoopB_Looping		EQU	1<<ASLoopF_Looping

CallSys	macro
	jsr	_LVO\1(a6)
	endm

TB	macro
	move.l	Toccata_base(a5),a6
	endm

;------------------------------------------------------------------------
begin
****************** Workbench Startup **********************************
EUS_Structure
	bra.w	fang
	EUSN_Identifier
	dc.l	0		;eus_next

	ifne	debug
	dc.w	-2
	else
	dc.w	0		;eus_Usernr
	endc
MyEPBase
	dc.l	0		;eus_EPBase
	dc.l	0		;eus_Freetable
	dc.l	0		;eus_Taskadr
	dc.l	0		;eus_unused1
	dc.l	0		;eus_unused2
	dc.l	SpecialJumps	;EUS_SpecialJumpTab
	dc.l	TagListe	;EUS_TagList
	dc.w	0		;eus_ticks
	dc.w	0		;eus_tickcounter
	dc.l	0		;EUIB_OnlyPlay	;eus_tickflags
;	dc.l	USMB_NewPreference!USMB_Configuration!USMB_KillModule!USMB_Zipwin!USMB_ChangeConfig;eus_msgflags
	dc.l	USMB_Configuration!USMB_KillModule!USMB_Zipwin!USMB_ChangeConfig;eus_msgflags
	dc.l	MyAnalyzername	;eus_PName
	dc.l	myBuggsname
	dc.l	myinfo
	dc.w	37		;eus_Kickstart
	dc.l	Eagleversion	;eus_EPVersion
	StructVer		;eus_version,revision
	dc.l	MyUsername	;eus_username
	dc.w	Project0left	;eus_winx
	dc.w	Project0top	;eus_winy
	dc.w	EUSB_openwin	;window opened
	dc.w	1		;pri
	dc.w	0		;flags

	dc.w	0,0		;EUS_Special2
	dc.b	0,$10,0,0	;EUS_Special3

ZoomPosX	equ	EUS_Special2
ZoomPosY	equ	EUS_Special2+2
ZoomState	equ	EUS_Special3	;Zoom or not zoom
OnMonoMode	equ	EUS_Special3+1	;Mono Modules Mode (untersch. Delay)

	StructDate		;EUS_Creatordate
	dc.b	0		;EUS_Priority

	dc.b	EUTY_Amplifier	;EUS_Type

	dc.w	0		;EUS_Reserved2
	dc.l	`TOCC`		;EUS_Reserved3;EUS_AMIDNr
	dc.l	0		;EUS_Reserved4

	dc.l	MyUPSStruct	;EUS_Reserved5

	dc.l	0		;EUS_Reserved6

TagListe:
	dc.l	EUT_AttnFlags,AFF_68020
	dc.l	EUT_EPSubItems,EP_Menu
	dc.l	EUT_SpecialinfoLNr,LNrE_SpecialInfo_8BitAmplifier
	dc.l	TAG_Done


	dc.b	`$VER: Eagleplayer Toccata Amplifier `
	ver
	dc.b	` `
	date
	dc.b	0
	even
SpecialJumps
	dc.l	Checkfeatures	;AMJ_CheckFeatures, Test ob Anforderungen des Replays erfüllt werden können
	dc.l	Init	;AMJ_Init	;Übergabe der Struktur/test&Init
	dc.l	StartInt;AMJ_StartInt	;Alloc Audio & Start Int
	dc.l	Stopint	;AMJ_StopInt	;Free Audio & Stop Int
	dc.l	End	;AMJ_End		;Mem freigeben, etc.

	dc.l	Copy_AS			;AMJ_Amplifier	;Einsprung, wenn neu gefüllte Amplifier-Struktur
					;vom Replayer übergeben wurde (meist nach DTP_Interrupt-
					;Abarbeitung)
	dc.l	0	;AMJ_PokeAdr	;nur für Noteplayer initialisieren,
	dc.l	0	;AMJ_PokeLen	;die auf die Hardware poken, wie
	dc.l	0	;AMJ_PokePer	;z.B. der Chipram Player, sonst
	dc.l	0	;AMJ_PokeVol	;auf 0 setzen, diese Jumps werden mit
	dc.l	0	;AMJ_DMAMask	;den selben Parametern aufgerufen, wie
					;die ENPP_Poke...
	dc.l	0	;AMJ_Command	;z.B. Filter
Fang
	move.l	4.w,a6

	ifeq	V37Gadtools
	cmp.w	#39,lib_version(a6)
	bge.s	.do39
	endc

	subq	#6,NG_Listview+6
.do39

	lea	datas,a5
	move.l	a5,a0
	move.w	#dataslen-1,d0
.clr	move.b	#0,(a0)+
	dbf	d0,.clr

	bsr	OpenLibs
	bne	InitError

	move	#-1,LastBoost

	move	#-1,Currentnumvoc(a5)		;kein Modul am Spielen

	;-------------------------------------------------------------------------------
	st	toccatafound(a5)
	
;	TB
;	move.l	a6,d0
;	beq	nohard$
;	tst.l	_tb_HardInfo(a6)
;	bne	hardfound$
;
;	;---- hier Requester, daß das Board nicht gefunden wurde ----
;nohard$
;	sf	toccatafound(a5)
;
;	lea	msg_Toccatalib(pc),a0
;	bsr	Merror
;
;	bra	notoccata$
;hardfound$
	bsr	MakeFreqList
	move.l	d0,Numfreq(A5)
	beq	InitError
notoccata$
	;----------------- Slider herrichten ----------------------------------------------
	subq.l	#1,d0
	move.l	d0,Freqslidermax

	;----------------------------------------------------------------------------------

	bsr	Makedefaults			;Default prefs setzen
	bsr	Loadconfig

	st	onsysfont(A5)

	moveq	#0,d7

	bsr	sendfirstmessage	;Message an Eagleplayer senden,daß
					;der Analyzer gern mal die Struktur-
					;Adresse haben möchte
	blt	endme	;Fehler aufgetreten

	bsr	HandleActions		;Auf Usereingaben reagieren

	tst.l	d7
	blt.s	endme
	bsr	sendlastmessage

	bsr	Stopint
	bsr	End
endme
	bsr	closedownwin
	bsr	closedownscreen

	bsr	Closelibs

	moveq	#0,d0
	rts
InitError
	bsr	Closelibs

	moveq	#-1,d0
	rts

******************************************************************************
* Liste der verfügbaren Abspielfrequenzen der verwendeten Hardware ermitteln *
******************************************************************************
;Input:  -
;Output: D0 - Anzahl der gefundenen Frequenzen
MakeFreqList:
	Push	d1-a6
	ifeq	testfreqlist
	
	lea	Freqlist(A5),a2
	moveq	#25-1,d2

	moveq	#0,d0
	moveq	#0,d1
loop$
	TB
	CallSys	T_NextFrequency
	move.l	d0,(a2)+
	beq	end$
	addq	#1,d1
	dbf	d2,loop$
end$
	move.l	d1,d0

	else
	lea	Freqlist(A5),a2

	move.l	#5512,(a2)+
	move.l	#11025,(a2)+
	move.l	#22050,(a2)+
	move.l	#44100,(a2)+
	move.l	#48000,(a2)+
	moveq	#5,d1
end$
	move.l	d1,d0

	endc

	Pop	d1-a6
	rts

******************************************************************************
*                   sucht geeignete Frequenz zum Abspielen raus              *
******************************************************************************
;Input:  D0 - gewünschte Frequenz
;Output: D0 - gefundene Frequenz
FindFrequency:
	push	d1-a6
	lea	datas,a5

	TB
	move.l	a6,d1
	beq	notoc$
	CallSys	T_FindFrequency
notoc$
	pop	d1-a6
	rts
******************************************************************************
*                   Abspielen über die Toccata.library starten               *
******************************************************************************
;Input:  -
;Output: D0 - Suxxess, 0=fail
StartPlay:
	Push	d1-a6
	lea	datas,a5
	tst.b	toccatafound(a5)
	beq	ok$

	move.l	usedmode,a0
	move.l	(a0),d0
	bsr	FindFrequency
	move.l	d0,PlayFreq	;wird auch von Mixroutine verwendet

	lea	RawBuffer1,a0	;dieser Puffer wird zuerst abgespielt und kann beim ersten Int neu gefüllt werden
	move.l	a0,FillBuffer1
	lea	RawBuffer2,a0
	move.l	a0,FillBuffer2

	ifne	secondInt
		lea	MixingBuffer1,a0
		move.l	a0,MixBuffer1
		lea	MixingBuffer2,a0
		move.l	a0,MixBuffer2
		clr.l	MixBufferPos
	endc

	move.l	my2ndsignal(a5),PlayMask
	move.l	mytask(a5),PlayTask

	lea	PlayTags(pc),a0
	TB
	CallSys	T_RawPlayBack
	tst.l	d0
	bne	ok$

	lea	msg_Starterror,a0		;Infotext ausgeben (Requester)
	bsr	Merror

	bsr	StopPlay

	moveq	#0,d0
ok$
	Pop	d1-a6
	rts
******************************************************************************
*                   Abspielen über die Toccata.library stoppen               *
******************************************************************************
;Input:  -
;Output: -
StopPlay:
	Push	All
	lea	datas,a5

	moveq	#0,d0
	TB
	move.l	a6,d1
	beq	notoc$
	CallSys	T_Stop
notoc$
	Pop	All
	rts

******************************************************************************************
Openlibs:
	move.l	4.w,a6
	moveq	#-1,d0
	jsr	_LVOallocsignal(a6)	;Signal allokieren
	move.l	d0,mysignal(a5)
	blt	error$

	moveq	#-1,d0
	jsr	_LVOallocsignal(a6)	;2. Signal allokieren (für Interrupt)
	tst.l	d0
	blt	error$
	move.l	d0,my2ndsignal(a5)

	suba.l	A1,A1
	JSR	_LVOfindtask(A6)
	move.l	d0,mytask(a5)

	lea	dos(pc),a1
	moveq	#37,d0			;Brauchen DOS V1.2,für Message,falls
	jsr	_LVOopenlibrary(a6)	;Start von 1.2/1.3 aus
	move.l	d0,_dos(a5)
	beq	error$

	lea	MsgPort1(a5),a4		;MSG Port Struktur initialisieren
	bsr	MakeMsgPort
	tst.l	d0
	blt	error$
	move.l	a4,MsgPort(A5)

	lea	int(pc),a1
	moveq	#37,d0
	jsr	_LVOopenlibrary(a6)
	move.l	d0,intsave(a5)
	beq	error$

	lea	graf(pc),a1
	moveq	#37,d0
	jsr	_LVOopenlibrary(a6)
	move.l	d0,grafsave(a5)
	beq	error$

	lea	gad(pc),a1

	ifeq	V37Gadtools
	moveq	#37,d0
	else
	moveq	#34,d0
	endc

	jsr	_LVOopenlibrary(a6)
	move.l	d0,gadsave(a5)
	beq	error$

	lea	toccata_name,a1
	moveq	#0,d0			;ab V6 wird TT_RawInt unterstützt
	CallSys	OpenLibrary
	move.l	d0,Toccata_base(a5)

	moveq	#0,d0
	rts
error$
	moveq	#-1,d0
	rts
******************************************************************************************
CloseLibs:
	push	all

	move.l	gadsave(a5),d0
	beq	nogadto$
	move.l	d0,a1
	move.l	4,a6
	jsr	_LVOcloselibrary(A6)
	clr.l	gadsave(A5)
nogadto$

	move.l	grafsave(a5),d0
	beq	nograf$
	move.l	d0,a1
	move.l	4,a6
	jsr	_LVOcloselibrary(a6)
	clr.l	grafsave(A5)
NoGraf$
	move.l	intsave(a5),d0
	beq	noint$
	move.l	d0,a1
	move.l	4,a6
	jsr	_LVOcloselibrary(a6)
	clr.l	intsave(a5)
noint$
	move.l	4,a6
	lea	msgport1(a5),a2
	move.b	mp_sigbit(a2),d0
	bmi.s	noport$
	move.b	#-1,mp_sigbit(a2)
	ext.w	d0
	ext.l	d0
	jsr	_LVOfreesignal(a6)
NoPort$
	move.l	4,a6
	move.l	_dos(a5),d0
	beq	nodos$
	move.l	d0,a1
	jsr	_LVOcloselibrary(a6)
	clr.l	_Dos(A5)
nodos$
	move.l	mysignal(a5),d0
	cmp.l	#-1,d0
	beq	nosignal$
	move.l	4,a6
	CallSys	FreeSignal
	move.l	#-1,mysignal(A5)
NoSignal$

	move.l	my2ndsignal(a5),d0
	cmp.l	#-1,d0
	beq	nosignal2$
	move.l	4,a6
	CallSys	FreeSignal
	move.l	#-1,my2ndsignal(A5)
NoSignal2$

	move.l	Toccata_base(a5),d0
	beq.s	notoccata$
	move.l	d0,a1
	CallSys	CloseLibrary
	clr.l	Toccata_base(a5)
notoccata$

	pop	all
	rts
******************************************************************************************
MakeMsgPort:
					;Message Port initialisieren
	move.l	4.w,a6
	moveq	#-1,d0
	jsr	_LVOallocsignal(a6)	;MSG Signal zuweisen lassen
	move.b	d0,mp_sigbit(a4)
	blt	.nosignal2		;Fehler

	move.b	#nt_msgport,ln_type(a4)
	move.b	#0,ln_pri(a4)
	move.b	#pa_signal,mp_flags(a4)

	move.l	mytask(a5),mp_sigtask(a4);mp_SigTask

	lea	mp_msglist(a4),a1
	Newlist	a1			;macro in Lists.i

	moveq	#0,d0
.nosignal2				;Fehler
	rts
********************************************************************
*                  Init & Open Window                              *
********************************************************************
Openwin:
	tst.l	winhandle(A5)
	bne.w	.endme

	clr.l	port(A5)

	move.l	intsave(a5),a6
	bsr	Setupscreen		;Public Screen holen
	bne	.Endme
	bsr	SetUpWin		;Fenster öffnen
	tst.l	d0
	bne	.Endme

	bsr	drawbevel

	move.l	Winhandle(a5),a0
	move.l	wd_userport(a0),a0	;User Port
	move.l	a0,port(a5)

	lea	EUS_Structure(pc),a2
	move.w	eus_flags(a2),d0
	and.w	#~EUSB_Show,d0

	move.l	winhandle(A5),d1		;Window
	beq.s	nowin$				;no Window opened,no change
						;of preferences
	or.w	#eusb_Show,d0			;set Flag: window is open

nowin$
	move.w	d0,eus_flags(a2)		;Save Flags
.endme
rtsA
	rts
DrawBevel
	move.l	gadsave(A5),a6
	move.l	winhandle(A5),a0
	move.w	wd_height(a0),d0
	cmp	offy(a5),d0
	beq.s	rtsA
	move.l  wd_RPort(a0),a2
	lea.l   IR(pc),a1
	move.l  Vi(a5),4(a1)

	move.w  #116,d0
	bsr	ComputeY
	move.w  offy(a5),d1
	add.w	d0,d1

	move.w	#300,d0
	bsr	ComputeX
	move.w	d0,d2

	move.w	#38,d0
	bsr	ComputeY
	move.w	d0,d3

	move.w  #4,d0
	bsr	ComputeX
	add.w   offx(A5),d0

	move.l  a2,a0
	jsr     _LVODrawBevelBoxA(a6)

	move.l	winhandle(A5),a0
	move.l  wd_RPort(a0),a2
	lea.l   IR(pc),a1

	move.w  #58,d0
	bsr	ComputeY
	move.w  offy(a5),d1
	add.w	d0,d1

	move.w	#300,d0
	bsr	ComputeX
	move.w	d0,d2

	move.w	#57,d0
	bsr	ComputeY
	move.w	d0,d3

	move.w  #4,d0
	bsr	ComputeX
	add.w   offx(A5),d0

	move.l  a2,a0
	jmp     _LVODrawBevelBoxA(a6)
ClearWin:
	move.l	winhandle(A5),a1
	move.w	wd_height(a1),d0
	cmp	offy(a5),d0
	beq.w	rtsA

	move.l	grafsave(a5),a6
	move.l	wd_rport(a1),a1
	moveq	#0,d0
	jsr	_LVOsetapen(A6)

	move.l	winhandle(A5),a1
	move.l	wd_rport(a1),a1
	moveq	#0,d0
	jsr	_LVOsetbpen(A6)

	move.l	winhandle(A5),a1
	move.l	wd_rport(a1),a1
	moveq	#1,d0			;RP_Jam2
	jsr	_LVOsetdrmd(A6)

	move.b	rp_areaptsz(a1),d4
	move.l	rp_areaptrn(a1),d5

	move.l	winhandle(A5),a1
	move.w	wd_width(A1),d2		;x2
	moveq	#0,d0
	move.b	wd_borderright(a1),d0
	sub.w	d0,d2

	move.w	wd_height(a1),d3
	moveq	#0,d0
	move.b	wd_borderbottom(a1),d0
	sub.w	d0,d3

	move.l	wd_rport(a1),a1

	move.w	offx(a5),d0		;x1
	move.w	offy(A5),d1		;y1
	jsr	_LVOrectfill(a6)

	move.l	winhandle(A5),a0
	move.l	intsave(a5),a6
	jsr	_LVOrefreshwindowframe(A6)
	rts
*************** Window & Screen freigeben *************************
Closewin:
	bsr	closedownwin
	bra	closedownscreen
********************************************************************
*                  Init Message Struktur                           *
********************************************************************
Sendfirstmessage
	move.l	4,a6
	lea	Portname(pc),a1
	jsr	_LVOfindport(a6)
	tst.l	d0
	beq.s	.error

	move.l	d0,a0			;Portadresse

	move.l	msgport(a5),d3
	move.l	mytask(a5),d4
	move.l	my2ndsignal(a5),d5
	move.w	#USclass_Newuserprg,d6

	ifne	debug

	bsr	allocmsg
	beq.s	.error
	move.l	d0,a1			;Messageadresse

	move.w	#UM_sizeof-20,mn_length(a1)
	move.b	#nt_message,ln_type(a1) ;Message-Typ
	lea	begin(pc),a2
	move.l	a2,um_result(a1)
	move.w	#-2,UM_UserNr(a1)
	move.l	#USM_Userprg,UM_Type(a1)

	move.l	d3,mn_replyport(a1)	;Portadresse,an die
						;zurückgesendet wird
	move.l	d3,UM_Userport(a1)
	move.l	d4,UM_TaskAdr(a1)
	move.l	d5,UM_Signal(a1)
	move.w	d6,UM_class(a1)

	move.l	4,a6
	jsr	_LVOputmsg(a6)

	else
	bsr	sendmess
	endc

	moveq	#0,d7
	rts
.error
	moveq	#-1,d7
	rts
*******************************************************************************
sendmess:
	bsr	allocmsg
	bne.s	.ok
	rts
.ok
	move.l	d0,a1			;Messageadresse

	move.w	#UM_sizeof-20,mn_length(a1)
	move.b	#nt_message,ln_type(a1) ;Message-Typ

	ifne	debug
	move.w	saveusernr(a5),UM_UserNr(a1)
	else
	lea	begin(pc),a2
	move.w	EUS_Usernr(A2),UM_UserNr(a1)
	endc

	move.l	#USM_Userprg,UM_Type(a1)

	move.l	d3,mn_replyport(a1)	;Portadresse,an die
						;zurückgesendet wird
	move.l	d3,UM_Userport(a1)
	move.l	d4,UM_TaskAdr(a1)
	move.l	d5,UM_Signal(a1)
	move.w	d6,UM_class(a1)

	move.l	4,a6
	jmp	_LVOputmsg(a6)
******************************************************************************
* Abschiedsgruß an Eagleplayer,der dann weiß,daß der Analyzer geendet hat    *
******************************************************************************
Sendlastmessage:
	move.l	4,a6
	lea	Portname(pc),a1	;EaglePlayer finden
	jsr	_LVOfindport(a6)
	tst.l	d0
	beq.w	.ok	;Eagleplayer hat sich schon verabschiedet

	move.l	d0,a0			;Portadresse
	move.l	msgport(a5),d3
	moveq	#0,d4
	moveq	#0,d5
	move.w	#USclass_exit,d6

	bsr	sendmess
.wait
	move.l	MSGport(a5),a0
	jsr	_LVOwaitport(a6)
	move.l	MSGport(a5),a0
	jsr	_LVOgetmsg(a6)
	tst.l	d0
	beq.s	.wait
	move.l	d0,a1
	cmp.l	#USM_Userprg,UM_Type(a1)
	beq.s	.meine
.nichtmeine
	jsr	_LVOreplymsg(a6)
	bra.s	.wait
.meine
.ok
	rts

	*----------------------- Gibt die Return-Structure frei -------------------*
FreeCommandStruct:
		push	all
		tst.l	d0
		beq	.Return
		move.l	d0,a4

.NextStruct:	moveq	#0,d0
		cmp.l	a4,d0
		beq.w	.Return
		move.l	a4,a1
		move.l	(a1),a4
		move.l	EPT_StringSize(a1),d0
		beq.s	.StructFree
		move.l	4.w,a6
		jsr	_LVOFreeMem(a6)
.StructFree:	bra.b	.NextStruct
.Return:
		pop	all
		rts

*******************************************************************
*      Public Screen ranholen und Visual Info anfordern           *
*******************************************************************
SetupScreen
	move.l	Intsave(a5),a6
	lea	begin(pc),a0
	move.l	eus_epbase(a0),d0
	beq.s	.noep
	move.l	d0,a0
	move.l	EPG_Pubscreen(A0),d0
	move.w	EPG_Wordreserved7(A0),word7(A5)
.noep
	move.l	d0,a0
	jsr	_LVOLockPubScreen(a6)
	move.l	d0,MyPubscreen(A5)
	beq.s	.error

	move.l	mypubscreen(A5),a0
	move.l	Gadsave(A5),a6
	suba.l	a1,a1
	jsr	_LVOGetVisualInfoA(a6)
	move.l	d0,Vi(A5)
	beq.s	.error     
	moveq	#0,d0
	rts
.error
	moveq	#-1,d0
	rts
*******************************************************************
*      Public Screen ranholen und Visual Info anfordern           *
*******************************************************************
CloseDownScreen:
	push	all
	
	move.l	Gadsave(a5),a6
	move.l	Vi(A5),d0
	beq.s	.novi
	move.l	d0,a0
	jsr	_LVOFreeVisualInfo(a6)
	clr.l	Vi(A5)
.novi
	move.l	Intsave(A5),a6
	suba.l	a0,a0
	move.l	Mypubscreen(A5),d0
	beq.s	.nopub
	move.l	d0,a1
	jsr	_LVOUnlockPubScreen(a6)
	clr.l	Mypubscreen(A5)
.nopub
	pop	all
	rts
GetFont
	tst.b	onsysfont(A5)
	beq.s	.stand

	move.l	grafsave(A5),a6
	lea.l	MyRastPort(a5),a3
	move.l	a3,a1
	jsr	_LVOInitrastport(A6)
	move.l	a3,a1
	lea.l	Attr(a5),a0
	jsr	_LVOAskFont(A6)
	lea.l	Attr(a5),a0
	jsr	_LVOopenfont(A6)
	move.l	d0,fontadr(A5)
	beq.s	.stand
	move.l	d0,a1
	rts
.stand
	move.l	mypubscreen(A5),a1
	lea.l	sc_RastPort(a1),a1
	move.l	rp_Font(a1),a1
	rts
ComputeFont:
	bsr	GetFont

	lea.l	Attr(a5),a0
	move.l	a0,Font(A5)

	move.l  LN_NAME(a1),ta_Name(a0)
	move.w  tf_YSize(a1),ta_YSize(a0)
	move.w  tf_XSize(a1),FontX(A5)
	move.w  tf_YSize(a1),FontY(A5)

	move.l	fontadr(A5),d0
	beq.s	.nofree
	move.l	d0,a1
	move.l	grafsave(A5),a6
	jsr	_LVOclosefont(A6)
.nofree
	move.l	mypubscreen(A5),a0
	move.b	sc_WBorLeft(a0),d0
	ext.w	d0
	move.w	d0,OffX(A5)

	move.l	sc_font(A0),a1
	move.w	ta_YSize(a1),d0

	addq.w	#1,d0
	move.b	sc_WBorTop(a0),d1
	ext.w	d1
	add.w	d1,d0
	move.w	d0,OffY(A5)

	tst.w	d2
	beq.s	CompDone
	tst.w	d3
	beq.s	CompDone
	move.w	d2,d0
	bsr	ComputeX

	add.w   OffX(A5),d0
	move.b	sc_WBorRight(a0),d1
	ext.w	d1
	add.w	d1,d0
	cmp.w	sc_Width(a0),d0

	ifne	test
	bra.s	Usetopaz
	endc

	bhi.s	UseTopaz
	move.w	d0,d2

	move.w	d3,d0
	bsr	ComputeY
	add.w	OffY(a5),d0
	move.b	sc_WBorBottom(a0),d1
	ext.w	d1
	add.w	d1,d0
	cmp.w	sc_Height(a0),d0
	bhi.s	UseTopaz
	move.w	d0,d3
CompDone:
	rts
UseTopaz:
	add.w   OffX(A5),d2
	move.b	sc_WBorRight(a0),d1
	ext.w	d1
	add.w	d1,d2

	add.w	OffY(a5),d3
	move.b	sc_WBorBottom(a0),d1
	ext.w	d1
	add.w	d1,d3

	move.l	Font(A5),a0
	move.l	#TopazName,ta_Name(a0)
	move.w	#8,FontY(A5)
	move.w	#8,FontX(a5)
	move.w	#8,ta_YSize(a0)
	rts
ComputeX:
	move.l	d1,-(sp)
	move.w	FontX(a5),d1
	bra.s	ComputeItX
ComputeY:
	move.l	d1,-(sp)
	move.w	FontY(A5),d1
	mulu	d1,d0
	addq.w	#4,d0
	lsr.w	#3,d0
	move.l	(sp)+,d1
	rts
ComputeItX:
	mulu	d1,d0
	addq.w	#4,d0
	lsr.w	#3,d0
	move.l	(sp)+,d1
	rts

*------------ Hookfunktion, um aktuellen Modus farblich hervorzuheben ------*
*---------------- derzeit noch kein Support für "disabled"-Gadgets ---------*
*benutzte Globals:
* - grafsave+datas = Graphics Base
*
*Erkennung, ob Zeile hervorzuheben oder nicht:
* -  erstes Zeichen im darzustellenden Text ist ein "|"
	;a0:Hook
	;a1:Message
	;a2:Node
my_hook
	push	d1-a6

	move.l	lvdm_MethodID(a1),d1
	cmp.l	#LV_Draw,d1
	bne.w	.hi
	move.l	a1,a4
	move.l	lvdm_RastPort(a4),d7
	beq.w	.hi

	move.l	grafsave+datas,a6			;Graphics Base

	move.l	lvdm_DrawInfo(A4),d0
	beq.w	.hi
	move.l	d0,a1
	move.l	dri_Pens(a1),a1

	sf	d2
	move.l	ln_name(A2),a5		;
	cmp.b	#`|`,(a5)		; Test ob hervorzuheben oder nicht
	bne.s	.textpen
	st	d2

	addq.l	#1,a5
	move	highlighttextpen*2(a1),d0
	bra.s	.high
.textpen
	move	textpen*2(a1),d0
.high
	move	backgroundpen*2(a1),d6

	cmp.l	#LVR_SELECTED,lvdm_State(a4)
	bne.s	.normalBG
	move	FILLPEN*2(a1),d6
	move	textpen*2(a1),d0
	tst.b	d2
	beq.s	.normalBG
	move	highlighttextpen*2(a1),d0
.normalBG
	move	d6,d1
	moveq	#RP_Jam1,d2
	move.l	d7,a1
	jsr	_LVOsetabpendrmd(A6)

	move.w	lvdm_bounds+ra_minx(a4),d0
	move.w	lvdm_bounds+ra_miny(a4),d1
	move.l	d7,a1
	add	rp_TxBaseline(a1),d1
	jsr	_LVOMove(A6)

	move.l	d7,a1
	moveq	#RP_Jam2,d0
	jsr	_LVOsetdrmd(A6)

	move.w	lvdm_bounds+ra_maxx(a4),d5		;Begrenzung des Textes
	sub	lvdm_bounds+ra_minx(a4),d5		;auf Breite des
	blt	.hi					;Listviews, solange

	move.l	a5,a0					;Text
	moveq	#-1,d3					;bis der Text passt
.lop
	addq	#1,d3
	tst.b	(a0)+
	bne.s	.lop
.charloop
	move.l	d7,a1
	move.l	a5,a0					;Text
	move.w	d3,d0
	jsr	_LVOtextlength(A6)
	cmp.w	d5,d0
	blt.s	.ok
	subq.w	#1,d3
	bra.s	.charloop
.ok
	move	d0,d4
	move.w	d3,d0
	move.l	a5,a0					;Text
	move.l	d7,a1
	jsr	_LVOtext(A6)

	move.l	d7,a1
	move	d6,d0
	move	d6,d1
	moveq	#0,d2
	jsr	_LVOsetabpendrmd(A6)

	move	lvdm_bounds+ra_minx(a4),d0
	add	d4,d0
	move	lvdm_bounds+ra_miny(a4),d1
	move	lvdm_bounds+ra_maxx(a4),d2
	move	lvdm_bounds+ra_maxy(a4),d3
	move.l	d7,a1
	jsr	_LVORectfill(a6)	;freien Platz nach dem Text löschen
	
	pop	d1-a6
	moveq	#LVCB_OK,d0
	rts
.hi
	pop	d1-a6
	moveq	#LVCB_Unknown,d0
	rts


CreateGadgets:
	move.l	Gadsave(A5),a6
	lea.l	Project0GList(a5),a0
	jsr	_LVOCreateContext(a6)
	move.l	d0,a3
	tst.l	d0
	beq.w	.Project0CError

	moveq	#0,d3
	lea.l	Project0GTags(pc),a4
.Project0GL:
	move.l	4,a6
	lea.l	Project0NGads(pc),a0
	move.l	d3,d0
	mulu	#gng_SIZEOF,d0
	add.l	d0,a0
	lea.l	BufNewGad(a5),a1
	moveq	#gng_SIZEOF,d0
	jsr	_LVOCopyMem(a6)
	lea.l	BufNewGad(a5),a0
	move.l	Vi(a5),gng_VisualInfo(a0)
	move.l	Font(a5),gng_TextAttr(a0)

	move.w	gng_LeftEdge(a0),d0
	bsr	computex
	add.w	OffX(a5),d0
	move.w	d0,gng_LeftEdge(a0)

	move.w	gng_TopEdge(a0),d0
	bsr	computey
	add.w	OffY(a5),d0
	move.w	d0,gng_TopEdge(a0)

	move.w	gng_Width(a0),d0
	bsr	computex
	move.w	d0,gng_Width(a0)

	move.w	gng_Height(a0),d0
	bsr	computey
	move.w	d0,gng_Height(a0)

	move.l	Gadsave(a5),a6
	lea.l	Project0GTypes(pc),a0
	moveq	#0,d0
	move.l	d3,d1
	asl.l	#1,d1
	add.l	d1,a0
	move.w	(a0),d0
	move.l	a3,a0
	lea.l	BufNewGad(a5),a1
	move.l	a4,a2
	jsr	_LVOCreateGadgetA(a6)
	tst.l	d0
	bne.s	.Project0COK
	bra	.Project0CError
.Project0COK:
	move.l	d0,a3
	move.l	d3,d0
	asl.l	#2,d0
	lea.l	Project0Gadgets(a5),a0
	add.l	d0,a0
	move.l	a3,(a0)
.Project0TL:
	tst.l	(a4)
	beq.s	.Project0DN
	addq.w	#8,a4
	bra.s	.Project0TL
.Project0DN:
	addq.w	#4,a4
	addq.w	#1,d3
	cmp.w	#Project0_CNT,d3
	bmi	.Project0GL
.Project0CError
	rts
*************************************************************************
*            Fenster öffnen, Gadgets und Menüs init                     *
*************************************************************************
SetUpWin:
	movem.l d1-d4/a0-a4/a6,-(sp)

	move.l	mypubscreen(a5),a0
	move.l  sc_Font(a0),a1
	move.w  ta_YSize(a1),d3
	addq.w  #1,d3
	move.b  sc_WBorTop(a0),d0
	ext.w   d0
	add.w	d3,d0
	move.w	d0,offy(a5)

	move.b  sc_WBorLeft(a0),d0
	ext.w   d0
	move.w	d0,offx(a5)

	move.w	#Project0Width,d2
	move.w	#Project0Height,d3

	bsr	ComputeFont
	move.l	mypubscreen(A5),a0

	move.l	d2,ahawidth
	move.l	d3,ahaheight

	move.l	d2,d0
	move.l	d0,d4

	moveq	#0,d2
	add.w	d2,d0
	add.w	OffX(a5),d0
	move.b	sc_WBorRight(a0),d1
	ext.w	d1
	add.w	d1,d0
	cmp.w	sc_Width(a0),d0
	bls.s	.Project0WOk
	move.w	sc_Width(a0),d0
	sub.w	d4,d0
	move.w	d0,d2
.Project0WOk:
	move.l	d3,d0
	move.l	d0,d4

	lea	begin(pc),a1
	move.w	eus_winy(a1),d3
	add.w	d3,d0

	add.w	OffY(A5),d0
	move.b	sc_WBorBottom(a0),d1
	ext.w	d1
	add.w	d1,d0
	cmp.w	sc_Height(a0),d0
	bls.s	Project0HOk
	move.w	sc_Height(a0),d0
	sub.w	d4,d0
	move.w	d0,d3
Project0HOk:
	move.l	Gadsave(A5),a6
	lea.l	Project0NewMenu0(pc),a0

	move.w	Hiercheck_Mono(pc),d0		;Menüeintrag: Mono aus den prefsssetzen
	and.w	#~Checked,d0
	move.b	Begin+OnMonoMode(pc),d1
	beq.s	.noset
	or.w	#Checked,d0
.noset	move	d0,HierCheck_Mono	

	lea.l	MTags0(pc),a1
	jsr	_LVOCreateMenusA(a6)

	move.l	d0,Project0Menus(A5)
	tst.l	d0
	beq	Project0MError
	move.l	d0,a0
	move.l	Vi(A5),a1
	lea.l	mtags0(pc),a2
	jsr	_LVOLayoutMenusA(a6)

	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d7
	lea	begin(Pc),a1
	move	eus_Winx(a1),d0
	move	eus_Winy(a1),d1
	move	ZoomPosX(a1),d2
	move	ZoomPosY(a1),d3

	move.l	ahawidth(pc),d4
	move.l	ahaheight(pc),d5
	move.l	#ZoomWidth,d6
	move	offy(A5),d7

	tst.b	ZoomState(a1)
	beq.s	.Normal
	exg.l	d0,d2
	exg.l	d1,d3
	exg.l	d4,d6
	exg.l	d5,d7
.normal
	lea.l	Project0WindowTags(pc),a1
	move.l	d0,Project0L+4-Project0WindowTags(A1)
	move.l	d1,Project0T+4-Project0WindowTags(A1)
	move.l	d4,Project0W+4-Project0WindowTags(A1)
	move.l	d5,Project0H+4-Project0WindowTags(A1)
	move.w	d2,ZoomStruct-Project0WindowTags(A1)
	move.w	d3,ZoomStruct+2-Project0WindowTags(A1)
	move	d6,ZoomStruct+4-Project0WindowTags(A1)
	move	d7,ZoomStruct+6-Project0WindowTags(A1)

	move.l	Intsave(A5),a6
	move.l	mypubscreen(a5),Pubadr-Project0WindowTags(a1)
	suba.l	a0,a0
	jsr	_LVOOpenWindowTagList(a6)
	move.l	d0,Winhandle(a5)
	tst.l	d0
	beq	Project0WError
.open13
	move.l	Winhandle(a5),a0
	move.l	Project0Menus(A5),a1
	jsr	_LVOSetMenuStrip(a6)

;	bsr	InitGadgets
	
	bsr	createGadgets

	bsr	AddGads

	moveq	#0,d0
Project0Done:
	movem.l	(sp)+,d1-d4/a0-a4/a6
	rts
Project0CError:
	moveq	#1,d0
	bra.s	Project0Done
Project0GError:
	moveq	#2,d0
	bra.s	Project0Done
Project0MError:
	moveq	#3,d0
	bra.s	Project0Done
Project0WError:
	moveq	#4,d0
	bra.s	Project0Done

AddGads:
	movem.l	d0-a6,-(sp)
	move.l	Project0GList(a5),d0
	beq.s	.nogads
	move.l	d0,a1

	moveq	#0,d1
.count
	move.l	d0,a0

	addq.l	#1,d1

	move.l	(A0),d0
	bne.s	.count

	move.w	d1,RealNumGadgets(A5)

	move.l	intsave(a5),a6
	move.l	winhandle(a5),a0
	moveq	#-1,d0
	moveq	#-1,d1
	suba.l	a2,a2
	jsr	_LVOaddglist(a6)

	move.l	Project0GList(a5),a0
	move.l	winhandle(a5),a1
	suba.l	a2,a2
	moveq	#-1,d0
	jsr	_LVOrefreshglist(a6)

	move.l	GadSave(a5),a6
	move.l	Winhandle(a5),a0
	suba.l	a1,a1
	jsr	_LVOGT_RefreshWindow(a6)

	bsr	UpdateList
.nogads
	movem.l	(sp)+,d0-a6
	rts
*************************************************************************
*            Fenster schließen, Gadgets und Menüs free                  *
*************************************************************************
Closedownwin:
	push	all
	move.l	Intsave(A5),a6
	move.l	Project0Menus(A5),a0
	cmpa.l	#0,a0
	beq	Project0NMenu
	move.l	Winhandle(a5),a0
	jsr	_LVOClearMenuStrip(a6)
	move.l	GadSave(a5),a6
	move.l	Project0Menus(A5),a0
	jsr	_LVOFreeMenus(a6)
	move.l	#0,Project0Menus(A5)
Project0NMenu:
	move.l	Intsave(A5),a6
	move.l	Winhandle(a5),d0
	beq.s	.nowin
	move.l	d0,a0
	jsr	_LVOCloseWindow(a6)
	clr.l	Winhandle(a5)
	clr.l	port(a5)
.nowin
	bsr	Freegadgets
	pop	all
	rts
FreeGadgets
	movem.l	d0-a6,-(sp)

	move.l	GadSave(a5),a6
	move.l	Project0GList(A5),a0
	cmpa.l	#0,a0
	beq	.nogad
	jsr	_LVOFreeGadgets(a6)
	clr.l	Project0GList(A5)
.nogad
	movem.l	(sp)+,d0-a6
	rts
*************************************************************
*    Gadgetadresse ausrechnen                               *
* Input D0 - Gadgetnummer (0 < X < MAX)                     *
*************************************************************
_Gadr
	lea	Gadgetadrs(a5),a0
	asl.l	#2,d0
	move.l	(a0,d0),a0
	rts
*************************************************************
*           Nachrichtenbearbeitung                          *
*************************************************************
HandleActions
	moveq	#0,d0
	moveq	#0,d3
.ma
	btst	d3,d0
	beq	.ma2

	tst.b	onplay
	beq.s	notestvolume$

	move.l	MyEPBase(pc),a1
	move.l	dtg_SndVol(A1),d0	; dtg_SndVol & dtg_SndLBal
	move.w	dtg_SndRBal(A1),d1	; dtg_SndVol & dtg_SndLBal
	
	cmp.w	tmpvol2(pc),d1
	bne.s	newvol$
	cmp.l	tmpvol(pc),d0
	beq.s	notestvolume$
newvol$
	bsr	makedivtabs
	
notestvolume$

.ma2
	move.l	gadsave(a5),a6

	move.l	port(a5),d0
	beq.s	.nowinny
	move.l	d0,a0
	jsr	_LVOGT_getimsg(a6)
	tst.l	d0
	bne	.msg
.nowinny
	move.l	4,a6
	
	move.l	msgport(a5),a0
	jsr	_LVOgetmsg(a6)
	tst.l	d0
	bne	.AN_msg

	bsr	UpdateDownGadgets
	bne	.ma

	moveq	#0,d0
	move.l	4,a6

	ifne	userprogram
	move.l	msgport(a5),a0
	move.b	mp_sigbit(a0),d1
	bset	d1,d0
	endc

	move.l	Port(a5),d2
	beq.s	.nomain
	move.l	d2,a0
	move.b	mp_sigbit(a0),d1
	bset	d1,d0
.nomain
	move.l	my2ndsignal(a5),d3	;Signal für Analyzer
	bset	d3,d0		;Signalbit für Abarbeitung des Analyzers selbst
				;(Auswertungsroutine namens "ANALYZE1")
	jsr	_LVOwait(a6)
	bra	.ma
;======================= Message an Hauptwindow ============================
.msg
	move.l	d0,a1
	move.l	im_class(a1),d7
	move.w	im_code(a1),d5 		<- Für Tastatur / Selnummer Listview
	move.l	im_Iaddress(a1),d6 	<- Für Gadgetabfrage
	move.l	im_seconds(a1),d2	<- für Doppelclick
	move.l	im_micros(a1),d3	<- auch f. Doppelclick
	jsr	_LVOGT_replyimsg(a6)

	cmp.l	#IDCMP_Changewindow,d7	;Refresh
	bne.s	.nochangewin
	lea	begin(pc),a1

	move.l	winhandle(a5),a0
	move	OffY(A5),d0
	cmp	wd_height(a0),d0
	bne.s	.setposun
	move.w	wd_leftedge(a0),ZoomPosX(a1)
	move.w	wd_topedge(a0),ZoomPosY(a1)
	st	ZoomState(a1)
	bra	.ma
.setposun
	move.w	wd_leftedge(a0),EUS_WinX(a1)
	move.w	wd_topedge(a0),EUS_Winy(A1)
	sf	ZoomState(a1)
	bra	.ma
.nochangewin
	cmp.l	#refreshwindow,d7	;Refresh
	bne.s	.noref
	pea	.ma(pc)
.ref
	bsr	clearwin

	move.l	gadsave(a5),a6
	move.l	winhandle(a5),a0	;*Window
	jsr	_LVOGT_beginrefresh(A6)

	move.l	winhandle(a5),a0	;*Window
	moveq	#1,d0
	jsr	_LVOGT_Endrefresh(A6)	

	bsr	drawbevel
	rts
	;------------------ Gadgets abfragen ------------------------
.noref
	cmp.l	#Gadgetup,d7
	bne.w	.notup

	move.l	d6,a1

	move.w	gg_gadgetid(A1),d4	;ID Für Gadgets

	bsr	TestGadgets
	bra	.ma
.notup
	cmp.l	#Gadgetdown,d7
	bne.w	.notgad

	move.l	d6,a1

	move.w	gg_gadgetid(A1),d4	;ID Für Gadgets

	bsr	TestDOWNGadgets
	bra	.ma

	;------------------------- Menüs abfragen ----------------------------
.menuloop
	move.l	temp(A5),a1
	move.w	mi_nextselect(A1),d5
	bra.s	.menuwei
.notgad:
	cmp.l	#menupick,d7
	bne.w	.nomenu
.menuwei
	move.w	d5,d0
	cmp.w	#menunull,d0
	beq	.ma

	move.l	Project0Menus(A5),a0
	move.l	intsave(a5),a6
	jsr	_LVOitemaddress(a6)
	move.l	d0,a1
	tst.l	d0
	beq	.ma
	move.l	d0,temp(A5)

	move.w	d5,d0
	and.w	#$1f,d0
	bne.s	.2ndmenu
	move.w	d5,d0
	and.w	#$7e0,d0
	bne.s	.noMonoMode

	move.w	mi_flags(a1),d0
	and.w	#checked,d0
	move.w	d0,d1
	lsr.w	#4,d0
	move.b	d0,begin+OnMonoMode

	move.w	Hiercheck_Mono(pc),d0
	and.w	#~Checked,d0
	or.w	d1,d0
	move.w	d0,Hiercheck_Mono
	bra	.menuloop
.noMonoMode
	cmp.w	#64,d0
	bne.s	.noabout		;1. Item (About) ?
	lea	Aboutmessage(pc),a0
	bsr	Merror
	bra	.menuloop
.noabout
	cmp.w	#96,d0			;2. Item (Hide)
	beq.w	.quitit
	cmp.w	#128,d0			;3. Item (Quit)
	beq	.killit
	bra	.menuloop
.2ndmenu				;2. Menü
	move.w	d5,d0
	and.w	#$7e0,d0
	bne.s	.noglobal

	move.w	mi_flags(a1),d0
	and.w	#checked,d0
	move.w	d0,d1
	lsr.w	#4,d0
	move.b	d0,Onglobal(A5)

	move.w	Hiercheck(pc),d0
	and.w	#~Checked,d0
	or.w	d1,d0
	move.w	d0,hiercheck

	bsr	SetVoic

	bra	.menuloop
.noglobal
	cmp	#64,d0
	bne.s	.nodefaults

	bsr	Makedefaults			;Default prefs setzen
	bsr	Updatelist

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.l	(A0,d0.w),d0
	bsr	CalcValues

	moveq	#0,d0
	bsr	SetPlaymode

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+7(a5),a0
	move.b	(A0,d0.w),d0
	bsr	setPrefetch

	bra	.menuloop
.nodefaults
	cmp.w	#96,d0
	bne	.nosavepref
	bsr	SaveConfig
.nosavepref
	bra	.menuloop
.nomenu
	cmp.l	#rawkey,d7
	bne	.nokey

	cmp.b	#$21,d5
	bne.s	.noS

	lea	Prefslist+6(a5),a0

	tst.b	onglobal(A5)
	bne.s	.sliPMglobal

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	clr.b	(A0,d0.w)
	bra.s	.sliPMup
.sliPMglobal
	moveq	#31-1,d0
.sliPMall
	clr.b	(A0)			;Playmode
	add.w	#10,a0
	dbf	d0,.sliPMall
.sliPMup
	bsr	UpdateList		;Später nur Listview update !!!!
	moveq	#0,d0
	bsr	SetPlaymode
	bra	.ma
.noS
	cmp.b	#$45,d5			;ESC
	beq	.quitit
	bra	.ma
.nokey
	cmp.l	#CloseWindow,d7
	bne	.ma
.quitit
	ifne	userprogram

	bsr	closewin

	move.l	4,a6
	lea	Portname(pc),a1
	jsr	_LVOfindport(a6)
	tst.l	d0
	beq.s	.endme		;kein Eagleplayerport->Ende des Programmes
	move.l	d0,a0			;Portadresse
	move.l	msgport(a5),d3
	move.l	mytask(a5),d4
	move.l	my2ndsignal(a5),d5
;	move.l	#-1,d5
	move.w	#USclass_Hide,d6		;DeActivate,d6
	bsr	sendmess
	bra	.ma

	endc
.endme
	moveq	#-1,d7
	rts
.killit
	move.l	4,a6
	lea	Portname(pc),a1
	jsr	_LVOfindport(a6)
	tst.l	d0
	beq.s	.endme		;kein Eagleplayerport->Ende des Programmes
	move.l	d0,a0			;Portadresse
	move.l	msgport(a5),d3
	move.l	mytask(a5),d4
	move.l	my2ndsignal(a5),d5
;	move.l	#-1,d5
	move.w	#USclass_Exit,d6		;DeActivate,d6
	bsr	sendmess
	bra	.ma

;===================== Message an Userprogramm Port =====================
	ifne	userprogram
.AN_msg
	move.l	d0,a1

	move.l	MSGPort(a5),UM_Userport(a1)

	lea	begin(pc),a2

	ifne	debug
	move.w	um_usernr(a1),saveusernr(A5)
	else
	move.w	EUS_Usernr(A2),UM_UserNr(a1)
	endc

	move.l	mytask(a5),UM_TaskAdr(a1)
	move.l	my2ndsignal(a5),d1
;	move.l	#-1,d1
	move.l	d1,UM_Signal(a1)

	move.w	UM_class(a1),d3		<-
	cmp.w	#USclass_exit,d3
	bne.w	.noex1

	clr.l	um_signal(a1)
	clr.l	um_taskadr(a1)
	clr.l	um_userport(a1)
.noex1
	move.l	UM_Type(a1),d7
	move.l	UM_structadr(a1),d6 	<-

	clr.w	UM_class(A1)

;	cmp.w	#USClass_NewPreference,d3
;	bne.s	nopref$
;
;	bsr	makedivtabs
;
;	move.l	UM_ArgString(a1),d0
;	beq.s	nopref$
;	clr.l	UM_Argstring(A1)
;	bsr	FreeCommandStruct
;
;	cmp.w	#EPNr_Volume,UM_Command(a1)
;	beq	NewVol$
;	cmp.w	#EPNr_Balance,UM_Command(a1)
;	bne	nothing$
;NewVol$
;nothing$
;nopref$

	cmp.w	#USclass_Saveconfig,d3
	bne	.nosavepref1
	bsr	SaveConfig
.nosavepref1
	cmp.w	#USclass_getconfig,d3		;when this command comes,set
						;the actual preferences into
						;the Eagleuser-Structure
						;(EUS_-structure at the be-
						;ginning of the program)
	bne	.noprev

	move.w	eus_flags(a2),d0
	and.w	#~EUSB_Show,d0

	move.l	winhandle(A5),d1		;Window
	beq.s	.prnowin			;no Window opened,no change
						;of preferences
	or.w	#eusb_Show,d0			;set Flag: window is open

	move.l	d1,a0				;Window
	move.w	wd_leftedge(a0),eus_winx(a2)	;Save Windowpostion
	move.w	wd_topedge(a0),eus_winy(a2)

;	move.w	wd_width(a0),d2
;	moveq	#0,d1
;	move.b	wd_borderleft(A0),d1
;	sub.w	d1,d2
;	move.b	wd_borderright(A0),d1
;	sub.w	d1,d2
.prnowin
	move.w	d0,eus_flags(a2)		;Save Flags
.noprev

	cmp.w	#USCLASS_Show,d3
	bne.s	.noshow

	tst.b	toccatafound(a5)
	beq.s	.noshow

	move.l	MYEpBase(pc),a0
	move.l	EPG_SomePrefs(a0),d0
	btst	#EGPRF_Iconify,d0
	bne.w	.noshow

	push	all
	bsr	Openwin
	pop	all
	tst.l	Winhandle(A5)
	beq.s	.noshow
	move	d3,UM_Class(a1)
.noshow

	cmp.w	#USclass_Hide,d3
	bne.s	.noclosewin

	lea	EUS_Structure(pc),a2
	move.w	eus_flags(a2),d0
	and.w	#~EUSB_Show,d0
	move.w	d0,eus_flags(a2)		;Save Flags

	bsr	Closewin
.noclosewin

	move.l	mn_replyport(a1),d0
	cmp.l	MSGport(a5),d0		 ;eine von uns abgeschickte Message ?
	beq.s	.noreply
	jsr	_LVOreplymsg(a6)
.noreply
	
	cmp.l	#USM_Userprg,d7	;Message zurückbekommen ?
	bne.s	.nomy

	move.b	#0,messagesent(a5)	;merken,daß Message-Struktur frei
	bra	.mess	;eventl. Message vom Esagle auswerten

.nomy
	cmp.l	#USM_Eagleplayer,d7	;Hat EaglePlayer was zu melden ?
	bne.w	.noeagle		;nö
.mess

;	lea	begin(pc),a0
;	move.l	eus_epbase(a0),a0
;	move.b	EPG_Wordreserved7(a0),d0
;	beq	.killit

;	move.l	d6,an_structadr(a5)
.refre
	cmp.w	#USclass_Dummy,d3	;leere Message,nur neue Analyzer-
	beq.w	.ma			;adresse bekommen
	cmp.w	#USclass_killmodule,d3
	bne.s	.nokill

	move	#-1,Currentnumvoc(a5)
	bsr	MakeLV

.nokill
	cmp.w	#USclass_zipwin,d3
	bne.s	.nozip
.setzip
	move.l	4,a6
	move.l	winhandle(a5),d0
	beq	.ma
	move.l	d0,a0
	move.w	wd_height(a0),d0
	cmp.w	myhoehe1(a5),d0
	beq.w	.ma		;Window schon klein
.zip
	move.w	d0,-(sp)

	move.l	intsave(a5),a6
	jsr	_LVOzipwindow(a6)

	move.w	(sp)+,d4

	move.l	winhandle(a5),a2
.Zipwait:
	moveq	#2,d1
	move.l	_Dos(a5),a6
	jsr	_LVODelay(a6)

	cmp.w	wd_height(a2),d4
	beq.s	.zipwait

	bra	.ma
.nozip
	cmp.w	#USclass_unzipwin,d3
	bne.s	.nounzip

.clearzip
	move.l	4,a6
	move.l	winhandle(a5),d0
	beq	.ma
	move.l	d0,a0
	move.w	wd_height(a0),d0
	cmp.w	myhoehe1(a5),d0
	beq.s	.zip
	bra	.ma
.nounzip
	cmp.w	#USclass_exit,d3
	beq	.endme

;	cmp.w	#USclass_Show,d3
;	beq.s	.win
	cmp.w	#USclass_Activate,d3
	bne.w	.nowin

	tst.b	toccatafound(a5)
	beq	.killit
;.win
;	bsr	Openwin
;	bra	.ma
.nowin
	cmp.w	#USclass_NewConfig,d3	;is there a new config
	bne.w	.nonewcon		;no

	lea	begin(pc),a0		;start of program (EUS_-Structure)
	move.w	eus_flags(a0),d0	;get Flags
	btst	#eusf_openwin,d0	;Window open ?
	beq.s	.nowino
	bsr	openwin			;open it
	bra.s	.weio
.nowino
	bsr	closewin		;else close it
.weio
	lea	begin(pc),a0		;start of program (EUS_-Structure)
	move.l	winhandle(a5),d0	;windowaddress
	beq.s	.nothingtomove		;no Window , no movement

	move.l	d0,a1			;Window
	move.l	wd_wscreen(a1),a2	;Parent Screen

	move.w	eus_winx(a0),d0		;new X-position
	move.w	d0,d1			;save
	blt.s	.oldx			;less than 0 -> stop

	add.w	wd_width(a1),d1		;new position + Window-width
	cmp.w	sc_width(a2),d1		;bigger than Screenwidth ?
	bhi.s	.oldx			;then old X-position (Delta = 0)

	sub.w	wd_leftedge(a1),d0	;new - old X-position = Delta X
	bra.s	.gety
.oldx
	moveq	#0,d0			;Delta X = 0
.gety
	move.w	eus_winy(a0),d1		;new Y-position

	move.w	d1,d2			;save
	blt.s	.oldy			;less than 0 -> stop and take old

	add.w	wd_height(a1),d2	;new position + window-height
	cmp.w	sc_height(a2),d2	;bigger than Screenheight ?
	bhi.s	.oldy

	sub.w	wd_topedge(a1),d1	;new - old Y-position = Delta Y
	bra.s	.setdeltas
.oldy	moveq	#0,d1

.setdeltas
	move.l	intsave(a5),a6		;Intuition
	move.l	a1,a0			;Winhandle
	jsr	_LVOmovewindow(A6)
.nothingtomove
	lea	begin(pc),a0
	move.w	eus_flags(a0),d0
	btst	#eusf_zipwin,d0		;Zipwindow ?
	bne	.setzip			;yes
	bra	.clearzip		;no
.nonewcon
	bra	.ma
.noeagle
	bra	.ma
	endc
*********************** Finde Tag über EP Funktion ***************************
FindTag
	movem.l	a1/a5,-(sp)
	move.l	myEPBase(pc),a5
	move.l	EPG_FindTag(a5),a1
	jsr	(a1)
	movem.l	(sp)+,a1/a5
	rts
*****************************************************************
allocmsg
	movem.l	d1-a6,-(sp)
	move.l	4,a6
	moveq	#UM_Sizeof,d0
	move.l	#$10001,d1
	jsr	_LVOallocmem(A6)
	movem.l	(sp)+,d1-a6
	tst.l	d0
	rts
*****************************************************************
freemsg
;	moveq	#UM_sizeof,d0

	moveq	#0,d0
	move.w	mn_length(a1),d0
	add.w	#20,d0
	move.l	4,a6
	jsr	_LVOfreemem(A6)
	rts
******************************************************************************
*                       Ausgabe von Error-Messages                           *
*                 Input: a0 -> Zeiger auf Ausgabestring                      *
******************************************************************************
MERROR:
	movem.l	d0/a2-a3,-(sp)
	suba.l	a3,a3			;*Arguments
	lea	my_easygadget(pc),a2
	bsr	Errorout
	movem.l	(sp)+,d0/a2-a3
	rts
Errorout
	movem.l	d1-a6,-(sp)
	move.l	Intsave(a5),a6
	lea	my_easystruct(a5),a1

	move.l	a0,es_textformat(a1)

	move.l	a2,es_gadgetformat(a1)

	lea	my_easytitle(pc),a0
	move.l	a0,es_Title(a1)
	move.l	winhandle(a5),a0	;*Window
	suba.l	a2,a2			;*IDCMP_ptr
	jsr	_LVOeasyrequestargs(a6)			;!! durch Reqtools
							;ersetzen
	movem.l	(sp)+,d1-a6	
	rts

;============= Save Player Config Routine ===========================
SaveConfig:
	movem.l	d0-a6,-(sp)
	
	move.l	4.w,a6
	lea	dos(pc),a1
	moveq	#33,d0
	jsr	_LVOopenlibrary(A6)	;Open DOS
	tst.l	d0
	beq	.error
	move.l	d0,dosbase
	move.l	d0,a6

	move.l	myepbase(pc),a0
	move.l	EPG_ConfigDirArrayPtr(a0),d1
	moveq	#-2,d2			;access_read
	jsr	_LVOlock(a6)
	tst.l	d0
	beq	.nolock			;Path not found
	move.l	d0,d1
	jsr	_LVOcurrentdir(A6)
	move.l	d0,d7

	lea	savename(pc),a1
	move.l	a1,d1
	move.l	#1006,d2		;MODE_NEWFILE
	jsr	_LVOopen(A6)
	move.l	d0,d6
	beq.s	.fail

	move.l	d0,d1				;Handle
	lea	ConfigDatas(A5),a1
	move.l	a1,d2				;Adr
	move.l	#ConfigDatasEND-ConfigDatas,d3	;len
	jsr	_LVOwrite(a6)

	move.l	d6,d1
	jsr	_LVOclose(a6)
.fail
	move.l	d7,d1
	jsr	_LVOCurrentdir(A6)
	move.l	d0,d1
	jsr	_LVOUnlock(A6)
.nolock
	move.l	a6,a1
	move.l	4.w,a6
	jsr	_LVOcloselibrary(A6)
.error
	movem.l	(Sp)+,d0-a6
	rts
;============= Load Player Config Routine ===========================
Loadconfig:
	movem.l	d0-a6,-(sp)

	move.l	4.w,a6
	lea	dos(pc),a1
	moveq	#33,d0
	jsr	_LVOopenlibrary(A6)	;Open DOS
	tst.l	d0
	beq	.error
	move.l	d0,dosbase
	move.l	d0,a6

	move.l	myepbase(pc),a0
	move.l	EPG_ConfigDirArrayPtr(a0),d1
	moveq	#-2,d2			;access_read
	jsr	_LVOlock(a6)
	tst.l	d0
	beq	.nolock			;Path not found
	move.l	d0,d1
	jsr	_LVOcurrentdir(A6)
	move.l	d0,d7

	lea	savename(pc),a1
	move.l	a1,d1
	move.l	#MODE_Oldfile,d2		;MODE_NEWFILE
	jsr	_LVOopen(A6)
	move.l	d0,d6
	beq.s	.fail

	move.l	d0,d1				;Handle
	lea	ConfigDatas(A5),a1
	move.l	a1,d2				;Adr
	move.l	#ConfigDatasEND-ConfigDatas,d3	;len
	jsr	_LVOread(a6)

	move.l	d6,d1
	jsr	_LVOclose(a6)
.fail
	move.l	d7,d1
	jsr	_LVOCurrentdir(A6)
	move.l	d0,d1
	jsr	_LVOUnlock(A6)
.nolock
	move.l	a6,a1
	move.l	4.w,a6
	jsr	_LVOcloselibrary(A6)
.error
	movem.l	(sp)+,d0-a6
	rts

dosbase:	dc.l    0       ; Dos-Lib Basisadresse
savename:	dc.b	`Toccata_Amplifier.cfg`,0

	cnop	0,4
********************************************************************
*               initialize default preferences                     *
********************************************************************
Makedefaults:
	movem.l	d0-a6,-(sp)

	lea	Prefslist(a5),a0

	move.l	Numfreq(a5),d0			;Anzahl der gefundenen Frequenzen
	lsr.l	#1,d0				;durch 2 (somit genau die Mitte erwischt)
	lea	Freqlist(a5),a1
	move.l	(a1,d0.l*4),d0			;Rate
	moveq	#10,d1				;VBoost "1.0"
	move.w	#$0000+Samlen/10,d2		;Effect (Stereo+Delay 350bytes)
	moveq	#0,d4				;Flags

	moveq	#32-1,d3
.defaults
	move.l	d0,(a0)+			;mixrate.l
	move.w	d1,(a0)+			;vboost.w
	move.w	d2,(a0)+			;effect.w
	move.w	d4,(a0)+			;flags.w

	addq.w	#1,d1
	dbf	d3,.defaults

	movem.l	(sp)+,d0-a6
	rts
*****************************************************************************
*                        Gedrückte Gadgets abfragen                         *
* A1 - aktuelle Gadgetstruktur                                              *
* D4 - Gadget ID                                                            *
*****************************************************************************
TestGadgets:
	cmp.w	#GD_Listview,d4		;Listview-Gadget
	bne.s	.noidlv

	move.w	SelectedW(A5),d6	;aktuell angeclickter Modus
	move.w	d5,SelectedW(A5)

	cmp.w	d5,d6			;kein Doppelklick
	beq	.testdoub

	move.l	d2,Seconds(a5)
	move.l	d3,Micros(a5)

	bsr	UpdateList
	bra	.endit
.testdoub
	move.l	Seconds(a5),d0
	move.l	Micros(a5),d1
	move.l	d2,Seconds(a5)
	move.l	d3,Micros(a5)
	move.l	intsave(a5),a6
	jsr	_LVOdoubleclick(a6)
	cmp.l	#1,d0
	bne.w	.disp

	clr.l	Seconds(a5)
	
	mulu	#10,d6
	lea	Prefslist(a5),a0
	move.w	8(A0,d6.w),d0		;Flags.w (Bit0=disable)
	eor.w	#1,d0
	move.w	d0,8(a0,d6.w)
.disp
	bsr	UpdateList
	bra	.ma
.noidlv
	cmp.w	#GD_VBOOST,d4		;Volume Boost Slider-Gadget
	bne.s	.noidBoost

	sf	onvboostslider(A5)

	tst.b	onglobal(A5)
	bne.s	.sli2global

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+4(a5),a0
	move.w	d5,(A0,d0.w)
	bra.s	.sli2up
.sli2global
	lea	Prefslist+4(a5),a0
	moveq	#31-1,d0
.sli2all
	move.w	d5,(A0)
	add.w	#10,a0
	dbf	d0,.sli2all
.sli2up
	bsr	makedivtabs

;	bsr	UpdateList		;Später nur Listview update !!!!

	bsr	SetVBoost
	bsr	MakeLV			;Listview in Ordnung bringen
	bra	.ma
.noidBoost
	cmp.w	#GD_Samplefreq,d4
	bne.s	.noidsam1

	move.l	gg_specialinfo(a1),a0	;Stringinfo Struktur
	move.l	si_Longint(A0),d1	;Wert des Gadgets
	cmp.l	#4000,d1
	bgt.s	.ok1
	move.l	#4000,d1
.ok1
	cmp.l	#65500,d1		;78000,d1
	ble.s	.ok2
	move.l	#65500,d1		;78000,d1
.ok2
	bra.s	.sli1set
;	bra	.ma
.noidsam1
	cmp.w	#GD_MixingSlider,d4
	bne.s	.nosli

	sf	onmixingslider(A5)

	lea	Freqlist(a5),a0
	move.l	(a0,d5.w*4),d1
.sli1set
	tst.b	onglobal(A5)
	bne.s	.sli1global

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.l	d1,(A0,d0.w)
	bra.s	.sli1up
.sli1global
	lea	Prefslist(a5),a0
	moveq	#31-1,d0
.sli1all
	move.l	d1,(A0)
	add.w	#10,a0
	dbf	d0,.sli1all
.sli1up
;	bsr	UpdateList		;Später nur Listview update !!!!

	bsr	MakeLV
	bsr	SetRate
	bsr	SetLevel

	bsr	CalcValues

	tst.b	onplay
	beq.s	norestart$

	bsr	StopPlay
	bsr	StartPlay
norestart$
	bra	.endit
.nosli
	cmp.w	#GD_Playmode,d4		;Playmode Slider
	bne.s	.noPlmode

	sf	onPlaymodeslider(A5)
					;d5: -64 <-> 64
	tst.b	onglobal(A5)
	bne.s	.slipmodeG

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.b	d5,6(A0,d0.w)
	bra.s	.sliPMODEup
.slipmodeG

	lea	Prefslist+6(a5),a0
	moveq	#31-1,d0
.sliPMall
	move.b	d5,(A0)			;Playmode
	add.w	#10,a0
	dbf	d0,.sliPMall
.sliPMODEup
;	bsr	UpdateList		;Später nur Listview update !!!!
	bsr	MakeLV

	move.b	d5,d0
	bsr	SetPlaymode

	bra	.endit
.noPlmode

	cmp.w	#GD_Surlevel,d4
	bne.s	.nosurlev

	sf	onSurlevslider(A5)
					;d5: -64 <-> 64
	tst.b	onglobal(A5)
	bne.s	.slisurleG

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.b	d5,7(A0,d0.w)
	bra.s	.slisurlevUP
.slisurleG
	lea	Prefslist+7(a5),a0
	moveq	#31-1,d0
.sliSLall
	move.b	d5,(A0)			;Playmode
	add.w	#10,a0
	dbf	d0,.sliSLall
.slisurlevUP
;	bsr	UpdateList		;Später nur Listview update !!!!
	bsr	MakeLV

	move.w	d5,d0
	bsr	setPrefetch
	bra	.endit
.nosurlev

.endit
.ma
	rts
*****************************************************************************
*                       SliderGadgets auswerten                             *
*****************************************************************************
TestDOWNGadgets
	move.l	4.w,a6

	ifne	V37Gadtools
	moveq	#-1,d0
	else
	cmp.w	#39,lib_version(A6)
	endc

	blt	.endit

	cmp.w	#GD_MixingSlider,d4
	bne.s	.nosli

	st	onmixingslider(A5)
.nosli
	cmp.w	#GD_VBoost,d4
	bne.s	.nosli2

	st	onvboostslider(A5)
.nosli2
	cmp.b	#GD_Playmode,d4
	bne.s	.nosli3

	st	onPlaymodeslider(A5)
.nosli3

	cmp.w	#GD_Surlevel,d4
	bne.s	.nosurlev

	st	onSurlevslider(A5)
.nosurlev

.endit
	rts
UpdateDownGadgets
	move.l	4.w,a6
	cmp.w	#39,lib_version(A6)
	blt	.endit

	tst.b	onmixingslider(A5)
	beq.s	.nosli1
	
	moveq	#GD_MixingSlider,d0
	bsr	_GADR			;Gadgetadresse in A0
	move.l	a0,a1
	bsr	.testup

	lea	Freqlist(a5),a0
	move.l	(a0,d5.w*4),d1

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.l	d1,(A0,d0.w)

	bsr	SetRate
	bsr	CalcValues
	bra.w	.rts
.nosli1
	tst.b	onvboostslider(A5)
	beq.s	.nosli2
	
	moveq	#GD_VBoost,d0
	bsr	_GADR			;Gadgetadresse in A0
	move.l	a0,a1
	bsr	.testup

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+4(a5),a0
	move.w	d5,(A0,d0.w)

	bsr	SetVBoost
	bsr	makedivtabs
	bra.s	.rts
.nosli2
	tst.b	onPlaymodeslider(A5)
	beq.s	.nosli3

	moveq	#GD_Playmode,d0
	bsr	_GADR			;Gadgetadresse in A0
	move.l	a0,a1
	bsr	.testup

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+6(a5),a0
	move.b	d5,(A0,d0.w)

	move.b	d5,d0
	bsr	SetPlaymode
	bra.s	.rts
.nosli3
	tst.b	onSurlevslider(A5)
	beq.s	.nosurlev

	moveq	#GD_Surlevel,d0
	bsr	_GADR			;Gadgetadresse in A0
	move.l	a0,a1
	bsr	.testup

	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+7(a5),a0
	move.b	d5,(A0,d0.w)

	move.w	d5,d0
	bsr	setPrefetch
	bra.s	.rts
.nosurlev

.endit
	moveq	#0,d0
	rts
.rts
	moveq	#1,d0
	rts
.testup
	movem.l	d1-d4/d6-a6,-(sp)

	move.l	a1,d7
	move.l	_dos(a5),a6
	moveq	#1,d1
	jsr	_LVOdelay(a6)
	move.l	d7,a1

	move.l	a1,a0			;gad
	move.l	gadsave(A5),a6		;lib
	sub.l	a2,a2			;req

	lea	numboo(a5),a1
	lea	mytags(a5),a3		;tags
	move.l	#GTSL_Level,(A3)+
	move.l	a1,(a3)+
	clr.l	(A3)+
	lea	mytags(a5),a3		;tags

	move.l	winhandle(A5),a1	;win

	jsr	_LVOGT_Getgadgetattrsa(A6)

	move.l	numboo(a5),d5

	movem.l	(sp)+,d1-d4/d6-a6
	rts
*****************************************************************************
*                 aktuelle Anzahl von Stimmen selektieren                   *
* Input: d0 = Num Voices                                                    *
*****************************************************************************
SelectEntry:
	movem.l	d0-a6,-(Sp)
	lea	datas,a5

	subq.w	#2,d0
	bpl.s	.hi
	moveq	#0,d0
.hi	move.w	d0,SelectedW(A5)	;aktuell angeclickter Modus
	move	d0,Currentnumvoc(a5)

	bsr	UpdateList

	tst.l	winhandle(A5)
	beq.s	.err

	moveq	#GD_LISTVIEW,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTLV_Makevisible,(a3)+
	move.l	selectedL(a5),(a3)+
	clr.l	(a3)
	lea	mytags(a5),a3

	move.l	winhandle(A5),a1
	suba.l	a2,a2
	move.l	gadsave(A5),a6
	jsr	_LVOGT_Setgadgetattrsa(A6)
.err
	movem.l	(Sp)+,d0-a6
	rts
*****************************************************************************
*          Einsprung, was alles up to Date gebracht werden muß              *
*****************************************************************************
;;
UpdateList:
	tst.l	winhandle(a5)
	beq.s	.end
	movem.l	d0-a6,-(Sp)

	bsr	MakeLV			;Listview in Ordnung bringen
	bsr	SetVoic
	bsr	SetVBoost
	bsr	SetVBoostSlider
	bsr	SetRate
	bsr	SetLevel
	bsr	SetPlaymodeSlider
	bsr	SetSurlevelSlider
	movem.l	(sp)+,d0-a6
.end
	rts
SetPlaymodeSlider:
	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.b	6(A0,d0.w),d1		;Playmode: -64 .. 64
	ext.w	d1
	ext.l	d1

	moveq	#GD_Playmode,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTSL_Level,(A3)+
	move.l	d1,(a3)+
	clr.l	(A3)+
	bra	SetGAD
SetSurlevelSlider
	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.b	7(A0,d0.w),d1		;Playmode: -64 .. 64
	ext.w	d1
	ext.l	d1

	moveq	#GD_Surlevel,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTSL_Level,(A3)+
	move.l	d1,(a3)+
	clr.l	(A3)+
	bra	SetGAD
SetLevel:
	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.l	(A0,d0.w),d1		;Mixrate

	lea	Freqlist(A5),a0
	move.l	Numfreq(A5),d0
	subq.l	#1,d0
	moveq	#0,d3
loop$
	move.l	(a0)+,d2
	cmp.l	d2,d1
	beq	do$
	addq	#1,d3
	dbf	d0,loop$
do$
	move.l	d3,d1

	moveq	#GD_MixingSlider,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTSL_Level,(A3)+
	move.l	d1,(a3)+
	clr.l	(A3)+
	bra	SetGAD
SetRate
	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist(a5),a0
	move.l	(A0,d0.w),d1

	moveq	#GD_Samplefreq,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
;	move.l	#GTIN_Number,(A3)+
	move.l	#GTNM_Number,(A3)+
	move.l	d1,(a3)+
	clr.l	(A3)+
	bra	SetGAD
SetVBoost:
	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+4(a5),a0
	moveq	#0,d1
	move.w	(A0,d0.w),d1

	moveq	#GD_NumVBoost,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTTX_Text,(A3)+
	lea	numboo(a5),a1
	move.l	a1,(a3)+
	clr.l	(A3)+

	divu	#100,d1
	add.b	#` `,d1
	cmp.b	#` `,d1
	beq.s	.set
	add.b	#"0"-" ",d1
.set
	move.b	d1,(a1)+

	clr.w	d1
	swap	d1
	divu	#10,d1
	add.b	#`0`,d1
	move.b	d1,(a1)+

	swap	d1
	move.b	#`.`,(a1)+
	add.b	#`0`,d1
	move.b	d1,(a1)+

	clr.b	(a1)
	bra	SetGAD
SetVBoostSlider
	move.w	SelectedW(a5),d0
	mulu	#10,d0
	lea	Prefslist+4(a5),a0
	moveq	#0,d1
	move.w	(A0,d0.w),d1		;VolBoost

	moveq	#GD_VBoost,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTSL_Level,(A3)+
	move.l	d1,(a3)+
	clr.l	(A3)+
	bra	SetGAD
SetVoic:
	moveq	#GD_VOICES,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	lea	NumVoc(A5),a1
	move.l	#GTTX_Text,(A3)+
	move.l	a1,(a3)+
	clr.l	(A3)+

	;---------- hier noch test auf Global -------------
	tst.b	onglobal(a5)
	beq.s	.ori

	move.b	#`G`,(a1)+
	clr.b	(a1)
	bra.s	setgad
.ori
	move.l	SelectedL(a5),d0
	addq.l	#2,d0

	divu	#10,d0
	add.b	#"0",d0
	move.b	d0,(a1)+

	swap	d0
	add.b	#`0`,d0	
	move.b	d0,(a1)+

	clr.b	(a1)
SetGAD
	lea	mytags(a5),a3
	move.l	winhandle(A5),a1
	suba.l	a2,a2
	move.l	gadsave(A5),a6
	jsr	_LVOGT_Setgadgetattrsa(A6)
	rts
MakeLV:
	push	all
	move.l	4.w,a6				;nur irgendeine Librarybase benötigt

	tst.l	winhandle(A5)
	beq.w	.lv_rts

	push	d5
	bsr	remlist		;Liste abhängen

	lea	list(a5),a0
	newlist	a0
	lea	Nodes(a5),a4		;1. Node

	move	Currentnumvoc(a5),d5
	moveq	#0,d4
	
	moveq	#31-1,d7
	moveq	#2,d6
	lea	Prefslist(A5),a3
.nodeloop
	lea	list(A5),a0		;gleich nach Alloc anhängen
	move.l	a4,a1			;(erspart Arbeit)
	addtail
	lea	ML_Nodename(a4),a1
	move.l	a1,ln_name(A4)

	cmp	d4,d5
	bne.s	.nosele
	tst.b	onplay
	beq.s	.nosele

	cmp.w	#39,lib_version(a6)
	ifeq	V37Gadtools
	blo.s	.nosele
	else
	bra.s	.nosele
	endc

	move.b	#`|`,(a1)+
.nosele
	addq	#1,d4

	move.w	8(a3),d0		;Flags
	and.b	#1,d0
	beq.s	.nodis
	move.b	#`(`,(a1)+
.nodis
	move.b	#` `,(a1)+

	move.l	d6,d0
	moveq	#2,d1			;Anzahl der Stellen
	bsr	todez
	move.b	#`c`,(a1)+
	move.b	#`h`,(a1)+
	move.b	#`:`,(a1)+
	move.b	#` `,(a1)+

	move.l	(A3)+,d0		;Mixingrate
	moveq	#5,d1			;Anzahl der Stellen
	bsr	todez
	move.b	#` `,(a1)+

	moveq	#0,d0
	move.w	(A3),d0			;Volumeboost
	divu	#10,d0			;durch 100 (wg. Nachkomma)
	and.l	#$fff,d0
	moveq	#2,d1
	bsr	todez
	move.b	#`.`,(a1)+

	clr.l	d0
	move.w	(A3)+,d0		;Volumeboost
	divu	#10,d0	
	swap	d0			;Nachkommastelle
	add.b	#`0`,d0
	move.b	d0,(a1)+
	move.b	#` `,(a1)+

					;A3 steht auf Effektwort
	moveq	#" ",d1
	move.b	(a3)+,d0
	bpl.s	.hi_s
	neg.b	d0
	move.b	#`-`,d1
.hi_S	move.b	d1,(a1)+
	and.l	#$ff,d0
	moveq	#2,d1
	bsr	todez
	move.b	#` `,(a1)+

	move.b	(a3)+,d0
	and.l	#$ff,d0
	moveq	#2,d1
	bsr	todez

	move.b	#` `,(a1)+

	move.w	(a3),d0			;Flags
	and.b	#1,d0
	beq.s	.nodis2
	move.b	#`)`,(a1)+
.nodis2
	clr.b	(a1)

	addq.l	#2,a3

	addq.w	#1,d6
	lea	ML_Sizeof(a4),a4
	dbf	d7,.nodeloop

	pop	d5
	bsr	readdlist
.lv_rts
	pop	all
	rts
***************** Liste vom Listview-Gadget entfernen ****************
Remlist:
	movem.l	d0-a6,-(sp)
	tst.l	winhandle(a5)
	beq.s	.err

	moveq	#GD_LISTVIEW,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTLV_Labels,(a3)+
	move.l	#-1,(a3)+
	clr.l	(A3)
	lea	mytags(a5),a3

	move.l	winhandle(A5),a1
	suba.l	a2,a2
	move.l	gadsave(A5),a6
	jsr	_LVOGT_Setgadgetattrsa(A6)
.err
	movem.l	(sp)+,d0-a6
	rts
**************** Liste wieder an Gadget anhängen *********************
readdlist:
	movem.l	d0-a6,-(sp)
	tst.l	winhandle(A5)
	beq.s	.err

	moveq	#GD_LISTVIEW,d0
	bsr	_GADR			;Gadgetadresse in A0
	lea	mytags(a5),a3
	move.l	#GTLV_Labels,(a3)+
	lea	list(a5),a2
	move.l	a2,(a3)+
	move.l	#GTLV_Selected,(a3)+
	move.l	selectedL(a5),(a3)+
	clr.l	(A3)
	lea	mytags(a5),a3

	move.l	winhandle(A5),a1
	suba.l	a2,a2
	move.l	gadsave(A5),a6
	jsr	_LVOGT_Setgadgetattrsa(A6)

;	move.l	gadsave(A5),a6
;	move.l	winhandle(a5),a0
;	suba.l	a1,a1
;	jsr	_LVOGT_refreshwindow(A6)
.err
	movem.l	(sp)+,d0-a6
	rts
**************** Hex to decimal ASCII conversion ************************
ToDEZ
	movem.l	d0-a0/a2-a6,-(Sp)
	lea	dectable(pc),a0
	move.w	d1,d2
	lsl.w	#2,d2
	add.w	d2,a0
	subq.w	#1,d1
.loopl
	moveq	#-1,d3
	move.l	-(a0),d2
.loop2l
	addq.b	#1,d3
	sub.l	d2,d0
	bcc.s	.loop2l
	add.l	d2,d0
	add.b	#`0`,d3
	move.b	d3,(a1)+
	dbf	d1,.loopl
	movem.l	(sp)+,d0-a0/a2-a6
	rts

;*****************************************************************************
;*                        Noteplayer-Init/Mix Routinen                       *
;*****************************************************************************
;*****************************************************************************
;*                        Amplifier-Init/Mix Routinen                        *
;*****************************************************************************
Checkfeatures:
;          - Initplayer -> Übergabe A0: Tagliste
;                                   A5: EP Globals
;                       -> zurück   D0: 0=OK, <>0=Error
;
	move.l	#EPAMT_Flags,d0
	jsr	ENPP_FindTag(A5)
	beq	.err

	moveq	#1,d2
	move.l	d0,d1
	move.l	d0,d6
	and.l	#EPAMB_WaitForStruct,d6
	and.l	#EPAMB_8Bit,d0
	bne	.ok
	moveq	#2,d2
	btst	#EPAMF_8BitUnsigned,d1
	bne	.ok

	moveq	#3,d2
	btst	#EPAMF_16Bit,d1			;erstmal nur 16 Bit signed
	beq	.err
.ok
	move.l	#EPAMT_Audiostructs,d0
	jsr	ENPP_FindTag(A5)
	beq	.err
	move.l	d0,d7

	move.l	#EPAMT_NumStructs,d0
	jsr	ENPP_FindTag(A5)
	beq	.err
	move.l	d7,a0

	subq.w	#1,d0			;Anzahl der Audio-Strukturen
	blt	.err

	moveq	#0,d1
	moveq	#0,d3
	lea	(a0),a2
.countvoc
	tst.w	AS_LeftRight(a2)
	bpl.s	.addL
	bmi.s	.addR
	bra.s	.noADD
.addL
	cmp.w	#2,AS_Leftright(a2)
	beq	.err
	addq.w	#1,d1
	bra.s	.noADD
.addR
	addq.w	#1,d3
.noadd
	lea	as_sizeof(a2),a2
	dbf	d0,.countvoc

	move.w	d3,d0
	add.w	d1,d0
	beq	.err			;wie, was, gar nichts ?

	cmp	#3,d2
	bne.s	.normal8bit

	cmp	#1,d3
	bne	.err
	cmp	#1,d1
	bne	.err

.normal8bit

	subq.w	#2,d0
	bgt.s	.hi1
	moveq	#0,d0
.hi1
	mulu	#10,d0
	
	lea	Prefslist+datas,a1
	lea	(a1,d0.w),a1
	
	move.w	8(A1),d0		;Flags.w (Bit0=disable)
	and.b	#1,d0
	bne	.err			;Modus disabled !!

	moveq	#0,d0
	rts
.err
	moveq	#-1,d0
	rts


; Init/End
;          - Initplayer -> Übergabe A0: Tagliste
;                                   A5: EP Globals
;                       -> zurück   D0: 0=OK, <>0=Error
;
; Start-Stop: Startint (keine Übergabeargumente)
;
;             Stopint  (keine Übergabeargumente)
;
;---------------- Routinen für den 16 Stimmen 14 Bit Player --------------------
; Init/End
;          - Initplayer -> Übergabe A0: Tagliste
;                                   A5: EP Globals
;                       -> zurück   D0: 0=OK, <>0=Error
;
; Start-Stop: Startint (keine Übergabeargumente)
;
;             Stopint  (keine Übergabeargumente)
;
Init:
	tst.b	toccatafound+datas
	beq	.err

	move.l	#EPAMT_Flags,d0
	jsr	ENPP_FindTag(A5)
	beq	.err

	moveq	#1,d2
	move.l	d0,d1
	move.l	d0,d6
	and.l	#EPAMB_WaitForStruct,d6
	and.l	#EPAMB_8Bit,d0
	bne	.ok
	moveq	#2,d2
	btst	#EPAMF_8BitUnsigned,d1
	bne	.ok

	moveq	#3,d2
	btst	#EPAMF_16Bit,d1			;erstmal nur 16 Bit signed
	beq	.err
.ok
	move.w	d2,fformat

	move.l	#EPAMT_Audiostructs,d0
	jsr	ENPP_FindTag(A5)
	beq	.err
	move.l	d0,d7

	move.l	#EPAMT_NumStructs,d0
	jsr	ENPP_FindTag(A5)
	beq	.err
	move.l	d7,a0

	move	d0,numstructs

	subq.w	#1,d0			;Anzahl der Audio-Strukturen
	blt	.err

	moveq	#0,d1
	moveq	#0,d2
	lea	(a0),a2
.countvoc
	tst.w	AS_LeftRight(a2)
	bpl.s	.addL
	bmi.s	.addR
	bra.s	.noADD
.addL
	cmp.w	#2,AS_Leftright(a2)
	beq	.err
	addq.w	#1,d1
	bra.s	.noADD
.addR
	addq.w	#1,d2
.noadd
	lea	as_sizeof(a2),a2
	dbf	d0,.countvoc

	st	onplay

	move.w	d2,d0
	add.w	d1,d0
	beq	.err			;wie, was, gar nichts ?

	move.l	#mix,mixad1
	move.l	#mix2,mixad2

	cmp	#3,fformat
	bne.s	.normal8bit

	cmp	#1,d2
	bne	.err
	cmp	#1,d1
	bne	.err

	move.l	#mix16,mixad1
.normal8bit

	subq.w	#2,d0
	bgt.s	.hi1
	moveq	#0,d0
.hi1
	mulu	#10,d0
	
	lea	Prefslist+datas,a1
	lea	(a1,d0.w),a1
	move.l	a1,usedmode
	
	move.w	8(A1),d0		;Flags.w (Bit0=disable)
	and.b	#1,d0
	bne	.err			;Modus disabled !!

	move.w	d1,numleft
	move.w	d2,numright

	move.l	a0,epg_audiostruct(A5)	;Audiostruct setzen
	tst.l	d6			;Flag für "WaitforStruct" gesetzt ?
	beq.s	.normal
	lea	Extra_AS,a0		;ja, also eigene AS Struktur verwenden
.normal
	move.l	a0,myAudioStruct	;AudioStruct vom Replayer sichern
;	move.l	a0,0

	move.b	6(a1),d0		;Playmode
	bsr	SetPlaymode

	move.b	7(a1),d0
	bsr	setPrefetch

	bsr	InitTables
	bne.s	.err2

	move.w	numleft,d0
	add.w	numright,d0
	bsr	SelectEntry

	bsr	Copy_AS2

	moveq	#0,d0
	rts
.err
	moveq	#-1,d0
.err2
	sf	onplay
	rts

	;-------------------- (noch) keine Funktion -------------------
END:
	clr.b	onplay
	move	#-1,Currentnumvoc+datas		;kein Modul am Spielen

	bsr	myFreemem

	moveq	#0,d0
	rts

***************************************************************************
*              kopiert neue Audio-Struct auf die eigene AS Struktur rüber *
***************************************************************************
Copy_AS:
		push	all

		tst.b	onplay
		beq.w	.err

		move.l	MYEpBase(pc),a0
		move.l	epg_audiostruct(A0),d0
		beq.w	.err
		move.l	d0,a0			;Original

;		move.l	myAudioStruct(pc),a1	;meine Extra-Struktur
		lea	Extra_AS,a1

		move	numstructs(pc),d0
		subq	#1,d0
		bmi.w	.err

.all
		move.l	AS_ChangeFlags(a0),d1
		btst	#ASChF_Adr,d1
		beq.s	.noad
		move.l	AS_CurrentAdr(a0),AS_CurrentAdr(a1)
		clr.l	AS_CurrentPos(a1)
		clr.l	AS_CurrentFPos(a1)
		clr.b	AS_NoLoop(a1)
.noad
		btst	#ASChF_Len,d1
		beq.s	.nolen
		move.l	AS_SampleSize(a0),AS_SampleSize(a1)
.nolen
		btst	#ASChF_RepAdr,d1
		beq.s	.norepadr
		move.l	AS_RepeatAdr(a0),AS_Repeatadr(a1)
.norepadr
		btst	#ASChF_RepLen,d1
		beq.s	.noreplen
		move.l	AS_RepeatSize(a0),AS_RepeatSize(a1)
.norepLen
		move.w	AS_Period(a0),AS_Period(a1)
		move.w	AS_LeftVolume(a0),AS_LeftVolume(a1)
		move.w	AS_RightVolume(a0),AS_RightVolume(a1)
		move.w	AS_DmaBit(a0),AS_DmaBit(a1)
		move.w	AS_LeftRight(a0),AS_LeftRight(a1)
		move.b	AS_LoopFlag(a0),AS_LoopFlag(a1)
		clr.l	AS_ChangeFlags(a0)

		lea	AS_Sizeof(a0),a0
		lea	AS_Sizeof(a1),a1
		dbf	d0,.all

.err
		pop	all
		rts


Copy_AS2:
		push	all

		tst.b	onplay
		beq.s	.err

		move.l	myAudioStruct(pc),a1	;meine Extra-Struktur

		move.l	MYEpBase(pc),a0
		move.l	epg_audiostruct(A0),d0
		beq.s	.err
		move.l	d0,a0			;Original

		move	numstructs(pc),d0
		subq	#1,d0
		bmi.s	.err

.all
		moveq	#AS_Sizeof-1,d1
.cp		move.b	(a0)+,(a1)+
		dbf	d1,.cp

		dbf	d0,.all
.err
		pop	all
		rts

*************************************************************************
*              Mem für Tabellen besorgen und Tabellen init              *
*************************************************************************
InitTables:
	movem.l	d1-a6,-(Sp)
	
	move.l	#64*1024*2,d0
	moveq	#MEMF_PUBLIC!MEMF_FAST,d1
	move.l	4.w,a6
	jsr	_LVOallocmem(A6)
	move.l	d0,buff16l
	beq	myFreemem2			; Fehler beim Speicherallozieren

	move.l	#64*1024*2,d0
	moveq	#MEMF_PUBLIC!MEMF_FAST,d1
	jsr	_LVOallocmem(A6)
	move.l	d0,buff16r
	beq	myFreemem2			; Fehler beim Speicherallozieren
	
	move.l	#64*1024*2,d0
	moveq	#MEMF_PUBLIC!MEMF_FAST,d1
	move.l	4.w,a6
	jsr	_LVOallocmem(A6)
	move.l	d0,buff16effl
	beq	myFreemem2			; Fehler beim Speicherallozieren

	move.l	#64*1024*2,d0
	moveq	#MEMF_PUBLIC!MEMF_FAST,d1
	move.l	4.w,a6
	jsr	_LVOallocmem(A6)
	move.l	d0,buff16effr
	beq	myFreemem2			; Fehler beim Speicherallozieren

	move.l	#66*256*2,d0

	cmp.w	#3,fformat
	blo	no16it

	move.l	#$10000*2+256,d0		;65000 Werte mal Wortbreite
no16it
	move.l	d0,VTabsize
	moveq	#MEMF_PUBLIC!MEMF_FAST,d1
	move.l	4.w,a6
	jsr	_LVOallocmem(A6)
	move.l	d0,vtab
	beq.b	myFreemem2

	add.l	#255,d0
	and.l	#~$ff,d0
	move.l	d0,Vtabaddr

	bsr	makedivtabs
	bsr	Makevoltable

	movem.l	(sp)+,d1-a6
	moveq	#0,d0
	rts
***************************************************************************
*                 Speicher von Divtab / VolTab freigeben                  *
***************************************************************************
myFreemem
	movem.l	d1-a6,-(sp)
myFreemem2
	move.l	4.w,a6

	move.l	buff16l(pc),d0
	beq	no16bufl$
	move.l	d0,a1
	move.l	#64*1024*2,d0
	jsr	_LVOfreemem(A6)
	clr.l	buff16l
no16bufl$

	move.l	buff16r(pc),d0
	beq	no16bufr$
	move.l	d0,a1
	move.l	#64*1024*2,d0
	jsr	_LVOfreemem(A6)
	clr.l	buff16r
no16bufr$

	move.l	buff16effr(pc),d0
	beq	no16bufeffr$
	move.l	d0,a1
	move.l	#64*1024*2,d0
	jsr	_LVOfreemem(A6)
	clr.l	buff16effr
no16bufeffr$

	move.l	buff16effl(pc),d0
	beq	no16bufeffl$
	move.l	d0,a1
	move.l	#64*1024*2,d0
	jsr	_LVOfreemem(A6)
	clr.l	buff16effl
no16bufeffl$

	move.l	vtab(pc),d0
	beq.s	.empty1
	move.l	d0,a1
	move.l	vtabsize(pc),d0
	jsr	_LVOfreemem(A6)
	clr.l	vtab
.empty1
	movem.l	(sp)+,d1-a6
	moveq	#-1,d0
	rts
******************************************************************************
* Volume Tabelle erzeugen, für Einrechnung globaler Lautstärke, Balance usw. *
******************************************************************************
makedivtabs:
	push	all
	lea	datas,a5

	move.b	onplay(pc),d0
	beq.w	rts$

	move.l	usedmode(pc),d0
	beq	rts$
	move.l	d0,a0
	move.w	4(a0),d0			;VBoost (auf xx.x bezogen,
						;z.B. 082 für 8.2) 

	move.l	MyEPBase(pc),a1
	move.l	dtg_SndVol(A1),d2	; dtg_SndVol & dtg_SndLBal
	move.w	dtg_SndRBal(A1),d3	; dtg_SndVol & dtg_SndLBal
	move.l	d2,tmpvol
	move.w	d3,tmpvol2

	move.w	DTG_SndLBal(a1),d1	;Balance &
	mulu	DTG_SndVol(a1),d1	;Lautstärke
	mulu	d0,d1			;mal Boost
	divu.l	#10,d1			;durch 10 wg. Wertebereich

	move	#32767,d3		;max. Amplitude gesamt

	move	effectvol(pc),d4	;aufgemischter Effekt (Mono/Surround)
	beq	stereol$		;keiner -> weiter

	move	d1,d2			;
	mulu	d4,d2			;
	lsr.l	#6,d2			;Wertigkeit des Zusatzeffektes ermitteln

	add.l	d1,d2			;Gesamtlautstärke
	beq	stereol$

	mulu	d1,d3			;alte max. Amplitude
	divu.l	d2,d3			;in neue max. Amplitude umrechnen

	move	d1,d6			;alten Wert sichern
	mulu	d1,d1			;alter Wert ^2
	divu.l	d2,d1			;durch Gesamtlautstärke

stereol$
	move.l	buff16l(pc),d7
	beq	rts$
	move.l	d7,a0
	bsr	maketab$

	move	effectvol(pc),d5
	beq	stereo1$

	tst	d2
	bne	notzerol$
	moveq	#0,d1
	move	#32767,d3
	bra	zerol$
notzerol$
	move	#32767,d4		;max. Amplitude gesamt
	sub	d3,d4			;minus Amplitude Hauptsignal
	move	d4,d3			;=Amplidude Effektsignal

	sub	d1,d6			;Gesamtlautstärke - Lautstärke Hauptsignal
	move	d6,d1			;=Lautstärke Effektsignal
zerol$
	move.l	buff16effl(pc),d7
	beq	rts$
	move.l	d7,a0
	bsr	maketab$
stereo1$

	move.w	DTG_SndRBal(a1),d1	;Balance &
	mulu	DTG_SndVol(a1),d1	;Lautstärke
	mulu	d0,d1			;mal Boost
	divu.l	#10,d1			;durch 10 wg. Wertebereich

	move	#32767,d3		;max. Amplitude gesamt

	move	effectvol(pc),d4	;aufgemischter Effekt (Mono/Surround)
	beq	stereor$		;keiner -> weiter

	move	d1,d2			;
	mulu	d4,d2			;
	lsr.l	#6,d2			;Wertigkeit des Zusatzeffektes ermitteln

	add.l	d1,d2			;Gesamtlautstärke
	beq	stereor$		;wenn 0 -> weiter, sonst Divisionsfehler

	mulu	d1,d3			;alte max. Amplitude
	divu.l	d2,d3			;in neue max. Amplitude umrechnen

	move	d1,d6			;alten Wert sichern
	mulu	d1,d1			;alter Wert ^2
	divu.l	d2,d1			;durch Gesamtlautstärke

stereor$
	move.l	buff16r(pc),d7
	beq	rts$
	move.l	d7,a0
	bsr	maketab$

	move	effectvol(pc),d5
	beq	stereo2$

	tst	d2
	bne	notzeror$
	moveq	#0,d1
	move	#32767,d3
	bra	zeror$
notzeror$
	move	#32767,d4		;max. Amplitude gesamt
	sub	d3,d4			;minus Amplitude Hauptsignal
	move	d4,d3			;=Amplidude Effektsignal

	sub	d1,d6			;Gesamtlautstärke - Lautstärke Hauptsignal
	move	d6,d1			;=Lautstärke Effektsignal
zeror$
	move.l	buff16effr(pc),d7
	beq	rts$
	move.l	d7,a0
	bsr	maketab$
stereo2$

rts$
	pop	all
	rts

;-- Lautstärke / Balance / Volume Boost beachtende Umrechentabelle erstellen --
;Input: a0 = Tabelle, 128kB lang
;       d1 = Lautstärke für diese Tabelle, <<12
;       d3 = max. Amplitude
;       d0 = 1-> Werte negieren, 0 -> Werte vorzeichenrichtig
maketab$
	push	all
	and.l	#$ffff,d3

	add.l	#32768*2,a0			;Mitte der Tabelle
	lea	(a0),a1

	;1. Teil, positive Koeffizienten in 16 Bit

	move	#32768-1,d7			;32k Durchläufe
	moveq	#0,d2
	moveq	#12,d4
tab1$
	move	d2,d5

	mulu	d1,d5				;Wert mal Lautstärke
	lsr.l	d4,d5				;durch Bezugswert (64*64)

	cmp.l	d3,d5
	bls	lo1$
	move	d3,d5
lo1$
	move	d5,(a0)+
	addq	#1,d2
	dbf	d7,tab1$

	;2. Teil, negative Koeffizienten in 16 Bit

	move	#32768-1,d7			;32k Durchläufe
	moveq	#1,d2
tab2$
	move	d2,d5

	mulu	d1,d5				;Wert mal Lautstärke
	lsr.l	d4,d5				;durch Bezugswert (64*64)

	cmp.l	d3,d5
	bls	lo2$
	move	d3,d5
lo2$
	neg	d5
	move	d5,-(a1)
	addq	#1,d2
	dbf	d7,tab2$

	pop	all
	rts
****************************************************************************
*                        Volume Tabelle erzeugen                           *
****************************************************************************
Makevoltable:
	push	all
	
	move.b	onplay(pc),d0
	beq.w	.rts

	move.l	#32767,d0			;32767 = max. Ausschlag für 1 Kanal

	move.l	vtabaddr(pc),d1
	beq.s	.rts
	move.l	d1,a0

	moveq	#0,d3
	move.w	numleft(pc),d3
	cmp	numright(pc),d3
	bge.s	.take
	move	numright(pc),d3
.take
				; d3: max. # of Channels
	divu.l	d3,d0		; max. Amplitude für einzelnen Kanal bei x Kanälen

	moveq	#0,d7		; "index"

	cmp.w	#3,fformat
	beq	do16bitsigned

	cmp	#1,fformat
	beq.b	signed2

.lop	move	d7,d6
	tst.b	d7
	bmi.b	.above

	and	#127,d6
	move	#128,d5
	sub	d6,d5
	lsl	#8,d5
	move	d7,d6
	lsr	#8,d6

	mulu	d6,d5
	lsr.l	#6,d5

	divu	d3,d5
	neg	d5
	move	d5,(a0)+
	addq	#1,d7
	cmp	#256*65,d7
	bne.b	.lop
.rts
	pop	all
	rts

.above	and	#127,d6
	lsl	#8,d6

	move	d7,d5
	lsr	#8,d5
	mulu	d6,d5
	lsr.l	#6,d5

	divu	d3,d5
	move	d5,(a0)+
	addq	#1,d7
	cmp	#256*65,d7
	bne.b	.lop
	pop	all
	rts

signed2
.lop	move	d7,d6
	tst.b	d7
	bpl.b	.above

	and	#127,d6
	move	#128,d5

	sub	d6,d5
	lsl	#8,d5
	move	d7,d6
	lsr	#8,d6

	mulu	d6,d5
	lsr.l	#6,d5
	divu.l	d3,d5

	cmp.l	d0,d5
	bls	.lo1
	move	d0,d5
.lo1
	neg	d5
	move	d5,(a0)+

	addq	#1,d7
	cmp	#256*65,d7
	bne.b	.lop
	pop	all
	rts

.above	and	#127,d6
	lsl	#8,d6

	move	d7,d5
	lsr	#8,d5

	mulu	d6,d5			;Volume * Index
	lsr.l	#6,d5			;durch 64
	
	divu.l	d3,d5

	cmp.l	d0,d5
	bls	.lo2
	move	d0,d5
.lo2
	move	d5,(a0)+
	addq	#1,d7
	cmp	#256*65,d7
	bne.b	.lop
	pop	all
	rts

do16bitsigned:
	move	#32768-1,d7			;65k Durchläufe
	moveq	#0,d1
.tab1
	move	d1,d2

	divu.l	d3,d2

	cmp.l	d0,d2
	bls	.lo1
	move	d0,d2
.lo1
	move	d2,(a0)+

	addq	#1,d1
	dbf	d7,.tab1

	move	#32768-1,d7			;65k Durchläufe
	move	#32768,d1
.tab2
	move	d1,d2

	divu.l	d3,d2

	cmp.l	d0,d2
	bls	.lo2
	move	d0,d2
.lo2
	neg	d2
	move	d2,(a0)+

	subq	#1,d1
	dbf	d7,.tab2

	pop	all
	rts

Mode_Stereo	=	0
Mode_Mono	=	1
Mode_Surround	=	2
****************************************************************************
*                  Delay setzen für Surround Modus                         *
* Input: d0 = Wert/10                                                      *
****************************************************************************
setPrefetch:
	mulu	#10,d0
	bne.s	.hi1
	moveq	#4,d0
.hi1
	cmp.w	#samlen-4,d0
	ble.s	.lo
	move.w	#samlen-4,d0
.lo
	add	d0,d0
	move.w	d0,prefetch
	rts
***************************************************************************
*  Abspielmodus festlegen, sprich Auswahl zwischen Mono-Stereo-Surround   *
* Input: D0 - Stereo Basisbreite                                          *
***************************************************************************
SetPlaymode:
	movem.l	d0-a6,-(sp)

	move.l	usedmode,d1
	beq	nope$
	move.l	d1,a0
	move.b	6(a0),d0		;Playmode

	lea	copybufStereo,a4

	tst.b	d0			;Stereo Wiedergabe
	beq.s	.setit

	lea	copybufMono,a4

	tst.b	d0
	bmi.w	.setit			;Mono Wiedergabe

	lea	copybufSurround,a4	;Surround Wiedergabe
.setit

	tst.b	d0
	bpl.s	.hi
	neg.b	d0
.hi
	and.w	#127,d0
	move.w	d0,effectvol

	bsr	MakeDivtabs		;Tabellen erstellen

	move.l	a4,cbufad		;

nope$
	movem.l	(sp)+,d0-a6
	rts

;------------------ Routinen für den FastRamPlayer -----------------------
StartINT:
	push	d1-a6

	clr.l	tmpvol
	clr.w	tmpvol2

;-------------------- Puffer löschen -------------------------------------
	lea	RawBuffer1,a0
	move.w	#[ENDRawBuffer-RawBuffer1]/2-1,d0
.clr
	clr.w	(A0)+
	dbf	d0,.clr

	lea	StartBSSBuffer,a0
	move.w	#[ENDBSSBUFFER-StartBSSBuffer]/2-1,d0
.clr2
	clr.w	(a0)+
	dbf	d0,.clr2

;-------------------- Periodwerte berechnen ------------------------------

	bsr	CalcValues

	bsr	StartPlay
	beq	fail$

	bsr	InitUPS

	moveq	#0,d0
	pop	d1-a6
	rts
fail$
	pop	d1-a6
	moveq	#-1,d0
	rts

StopINT:
	bsr	StopPlay
	rts

CalcValues:
;	move.l	#46000,d7			;Samplingrate

	move.b	onplay(pc),d0
	beq.s	skipcalc

	move.l	usedmode,a0
	move.l	(a0),d0				;aktuelle Abspielrate aus Prefs holen
	bsr	FindFrequency
	move.l	d0,d1
	move.l	d0,d7

	move.l	#3546895,d2
	move.l	d2,d0
	move.l	d7,d1				;mixingrate(pc),d1
	divu	d1,d0
	move.l	d2,d1
	divu	d0,d1
	swap	d1
	clr	d1
	swap	d1
	move.l	d1,mrate			;Abspielrate für Mixroutine setzen

	move.l	d7,d1
	move.l	#14187580,d2
	move.l	d2,clock			;Clock Konstante der Amiga-Hardware zur 
	lsr.l	#2,d2				;Umrechnung der Periodwerte in Frequenzen

	move.l	d2,d0
	divu	d1,d0
	swap	d0
	clr	d0
	swap	d0
	move.l	d0,mixingperiod

	push	a1
	lea	myupsstruct,a1
	move.w	d0,ups_voice1per(a1)
	move.w	d0,ups_voice2per(a1)
	move.w	d0,ups_voice3per(a1)
	move.w	d0,ups_voice4per(a1)
	pop	a1
skipcalc
	rts
InitUPS:
	lea	myupsstruct,a1
	move.w	#UPSB_Adr!UPSB_LEN!UPSB_Per!UPSB_Vol!UPSB_DMACON,ups_flags(a1)
	move.w	#15,UPS_DmaCon(a1)
	clr.w	UPS_Enabled(a1)

	lea	UPSBuffer0a,a0
	move.l	a0,ups_voice1adr(A1)
	move.l	a0,ups_voice4adr(A1)

	lea	UPSBuffer1a,a0
	move.l	a0,ups_voice2adr(A1)
	move.l	a0,ups_voice3adr(A1)

	move	#SamLen*2*NumChipBuffers/2,d0
	move	d0,ups_voice1len(A1)
	move	d0,ups_voice2len(A1)
	move	d0,ups_voice3len(A1)
	move	d0,ups_voice4len(A1)

	moveq	#64,d0
	move.w	d0,ups_voice1vol(a1)
	move.w	d0,ups_voice2vol(a1)
	move.w	d0,ups_voice3vol(a1)
	move.w	d0,ups_voice4vol(a1)

	move.l	mixingperiod(pc),d0
	move.w	d0,ups_voice1per(a1)
	move.w	d0,ups_voice2per(a1)
	move.w	d0,ups_voice3per(a1)
	move.w	d0,ups_voice4per(a1)
	rts

;------------------------------- Puffertausch der zu füllenden Abspielpuffer ------------------------
	ifne	secondInt

Intserver:
	push	all

	ifne	speedtest
	move	#$f0f,$dff180
	endc

	move.l	FillBuffer1(pc),a1		;double Buffering handling
	move.l	FillBuffer2(pc),FillBuffer1
	move.l	a1,FillBuffer2			;in FillBuffer2 steht der genau jetzt zu füllende Puffer

	move.l	MixBuffer1,a0			;gerade umkopierter Puffer
	add.l	MixBufferPos,a0
	moveq	#512/16-1,d0
	move.l	#16,d5
copy$
	movem.l	(a0)+,d1-d4
	movem.l	d1-d4,(a1)
	add.l	d5,a1
	dbf	d0,copy$

	add.l	#512,MixBufferPos
	cmp.l	#Samlen*8,MixBufferPos
	blt	weiter$
	clr.l	MixBufferPos

	move.l	MixBuffer1,d0			;Puffer tauschen
	move.l	MixBuffer2,MixBuffer1		;
	move.l	d0,Mixbuffer2			;

	move.l	4.w,a6
	lea	CallBackInt2,a1			;Signal an Mixroutine, den in MixBuffer2
						;stehenden Puffer mit Daten zu füllen

	cmp.b	#NT_Interrupt,ln_type(a1)	;arbeitet Mixroutine noch ?
	bne.s	weiter$				;yep, somit kommen die Daten von ganz
						;allein (wenn auch verspätet)
	CallSys	Cause				
weiter$

	ifne	speedtest
	move	#$0,$dff180
	endc

	pop	all
	rts

	endc
;----------------------------------------------------------------------------------------------------
;------------------------------- Mixroutine Main Loop -----------------------------------------------
;----------------------------------------------------------------------------------------------------
DoMix:
	movem.l	d0-a6,-(Sp)

	move.l	MyEPBase(pc),a0
	move	EPG_Volume(a0),d0
	move	EPG_Balance(a0),d1
	cmp	tmpvolume(pc),d0
	bne.s	sendsig$
	cmp	tmpbalance(pc),d1
	beq.s	nosig$
sendsig$
	move	d0,tmpvolume
	move	d1,tmpbalance

	move.l	my2ndsignal+datas,d1
	moveq	#0,d0
	bset	d1,d0
	move.l	mytask+datas,a1
	move.l	4,a6
	jsr	_LVOSignal(a6)
nosig$

	ifne	speedtest
	move	#$0f0,$dff180
	endc


	ifeq	secondInt
	move.l	FillBuffer1(pc),d0		;double Buffering handling
	move.l	FillBuffer2(pc),FillBuffer1
	move.l	d0,FillBuffer2			;in FillBuffer2 steht der genau jetzt zu füllende Puffer
	endc

	move.l	myaudiostruct(pc),a4

	move	numstructs,d7
	subq.w	#1,d7
	blt.w	.noleft
	
	move.l	mixad1,a1
	lea	TempBuffer,a2
.loo
	tst.w	AS_LeftRight(a4)
	ble.s	.n
	movem.l	a1/a2/a4/d7,-(sp)
	ifne	benchmark2
	move.w	#$ff0,$dff180
	jsr	(a1)				; Mix
	move.w	#$000,$dff180
	else
	jsr	(a1)
	endc
	movem.l	(sp)+,a1/a2/a4/d7
	move	#1,chans
	lea	AS_Sizeof(a4),a4
	subq	#1,d7
	bra.b	.loo2

.n	lea	AS_Sizeof(a4),a4
	dbf	d7,.loo
	bra.b	.ddq

.loo2	cmp	#1,numleft
	beq.b	.ddq

	move.l	mixad2,a1
.loka	tst.w	AS_LeftRight(a4)
	ble.s	.n2

	movem.l	a1/a2/a4/d7,-(sp)
	jsr	(a1)
	movem.l	(sp)+,a1/a2/a4/d7
	
.n2	lea	AS_Sizeof(a4),a4
	dbf	d7,.loka

.ddq
.noleft
right:
	move.l	myaudiostruct(pc),a4

	move	numstructs,d7
	subq.w	#1,d7
	blt.w	.noright
	
	move.l	mixad1,a1
	lea	TempBuffer2,a2
.loo	tst.w	AS_LeftRight(a4)
	bge.s	.n

	movem.l	a1/a2/a4/d7,-(sp)
	jsr	(a1)
	movem.l	(sp)+,a1/a2/a4/d7
	move	#1,chans
	lea	AS_Sizeof(a4),a4
	subq	#1,d7
	bra.b	.loo2

.n	lea	AS_Sizeof(a4),a4
	dbf	d7,.loo
	bra.b	.ddq

.loo2	cmp	#1,numright
	beq.b	.ddq

	ifne	benchmark2
	lea	mix3,a1
	else
	move.l	mixad2,a1
	endc

.loka	tst.w	AS_LeftRight(a4)
	bge.s	.n2

	movem.l	a1/a2/a4/d7,-(sp)
	ifne	benchmark2
	move.w	#$00f,$dff180
	jsr	(a1)				; Mix
	move.w	#$000,$dff180
	else
	jsr	(a1)
	endc
	movem.l	(sp)+,a1/a2/a4/d7
	
.n2	lea	AS_Sizeof(a4),a4
	dbf	d7,.loka

.ddq

	lea	Tempbuffer,a0			;Quelladresse der gemixten Daten links
	lea	Tempbuffer2,a1			;Quelladresse der gemixten Daten rechts

	ifeq	secondInt
	move.l	FillBuffer2,a2			;Zieladresse
	else
	move.l	MixBuffer2,a2			;Zieladresse
	endc

	move.l	cbufad(pc),a3
	jsr	(a3)

	lea	Tempbuffer,a0			;Quelladresse der gemixten Daten links
	lea	Tempbuffer2,a1			;Quelladresse der gemixten Daten rechts
	bsr	CopyUps
	ifne	speedtest
	move	#$999,$dff180
	endc
.noright

	bsr	CopyASBack
	movem.l	(sp)+,d0-a6
	rts
;----------------------------------------------------------------------------------------------------
;                             gemixte Werte in UPS Struktur übertragen
;----------------------------------------------------------------------------------------------------
CopyUps:
	move.l	UsedUpsBuffer(pc),d0
	add.l	#Samlen*2,d0
	and.l	#Samlen*2*NumChipbuffers-1,d0
	move.l	d0,UsedUpsBuffer

	lea	UPSBuffer0a,a2
	lea	UPSBuffer1a,a3
	add.l	d0,a2
	add.l	d0,a3

	move	#samlen-1,d0
copy$
	move	(a0)+,d1
	move.b	(a0)+,d1
	addq.l	#1,a0
	move	d1,(a2)+

	move	(a1)+,d1
	move.b	(a1)+,d1
	addq.l	#1,a1
	move	d1,(a3)+

	dbf	d0,copy$
	rts
;-----------------------------------------------------------------------------------------------------
CopyASBack:
		move.l	myAudioStruct(pc),d0
		cmp.l	#Extra_AS,d0
		bne.s	.out
		move.l	d0,a0

		move.l	MYEpBase(pc),a1
		move.l	epg_audiostruct(A1),d0
		beq.w	.out
		move.l	d0,a1

		move	numStructs(pc),d0
		subq	#1,d0
.cp
		movem.l	(a0)+,d1-d7/a2-a6	;7+5 Register = 12*4=48 Bytes
		movem.l	d1-d7/a2-a6,(a1)
		lea	12*4(a1),a1
		movem.l	(a0)+,d1-d7/a2-a6	;7+5 Register = 12*4=48 Bytes
		movem.l	d1-d7/a2-a6,(a1)
		lea	12*4(a1),a1
		move.l	(a0)+,(a1)+
		dbf	d0,.cp
.out
		rts
;-----------------------------------------------------------------------------------------------------
;-----------------------------------------------------------------------------------------------------
;--------------------------------- 8 Bit Mixing Routine (Part1 - Move Data) --------------------------
;-----------------------------------------------------------------------------------------------------
;-----------------------------------------------------------------------------------------------------
;-------------------- 8 Bit Mixing Routine (Part1 - Move Data) ----------------
mix:
	moveq	#0,d7
	move	#samlen*2,d7
	
;	cmp.w	#34*4,AS_Period(a4)
;	blo	.ty

	tst.w	AS_Period(a4)
	beq	.ty

	tst.b	AS_NoLoop(a4)
	bne	.ty			;noloop

	tst.b	AS_DmaBit(a4)
	beq	.ty			;noloop

	tst.l	AS_Currentadr(a4)	;pos (addr)
	bne.s	.dw

	clr.l	AS_CurrentPos(a4)
	move.l	AS_RepeatAdr(A4),AS_CurrentAdr(a4)
	beq	.ty
	move.l	AS_RepeatSize(a4),AS_SampleSize(a4)
	beq	.ty

.dw
	move.l	clock(pc),d4		;Amiga-Clockwert zur Umrechnung Periode->Frequenz (*4 wg. Periode<<2)
	moveq	#0,d0
	move.w	AS_Period(a4),d0	;Periode*4

	divu.l	d0,d4			;Clock/Periode=Frequenz
	lsl.l	#8,d4			;
	lsl.l	#4,d4			;<<12

	move.l	mrate(pc),d0		;aktuelle Abspielrate
	lsr.l	#4,d0
	divu.l	d0,d4			;in D4 nun Additionswert nach jedem bearbeiteten Byte
	swap	d4

	move.l	vtabaddr(pc),a3
	moveq	#0,d0
	move	AS_LeftVolume(a4),d0
	add	d0,d0
	lsl.l	#8,d0
	add.l	d0,a3			; Position in volume table

	move.l	AS_Currentadr(a4),a0	;pos (addr)
	move.l	AS_CurrentPos(a4),d6
	add.l	d6,a0			;aktuelle Position + dem schon gespielten

	moveq	#0,d0
	move.w	AS_CurrentFPOS(a4),d0	;fpos
	swap	d0			;nach oben

	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d5

	move.l	d4,d1			;Counter für Zoom
	swap	d1			;count bis zum nächsten Byte
	lsl.l	#3,d1			;Mal 8 (wg. 8 * Mix)
	swap	d1			;Overflow count, also wieviele neue Bytes zu holen sind
	move.l	d1,a1

	btst	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)
	bne.w	.Ping_Init

	neg.l	d6			;
	add.l	AS_SampleSize(a4),d6	;Gesamtlänge + (- gespielte Länge) = übrige Länge
	bpl.s	.Checkd6
	move.l	AS_SampleSize(a4),d6	;Gesamtlänge + (- gespielte Länge) = übrige Länge
	move.l	AS_Currentadr(a4),a0	;pos (addr)
.Checkd6
	cmp.l	#$7fff,d6
	bls.s	.restart
	move.l	#$7fff,d6
.restart

.leii	subq	#8,d7
	blt.s	.lep

	move.l	a1,d1
	add.l	d0,d1			;+ aktuelle Position, wieviele Bytes schon weg sind
	addx	d5,d1			;+Overflow
	cmp	d6,d1			;größer als übrige Bytes ?
	bhs.s	.lep			;yup

	rept	4
	move.b	(a0,d0),d2
	add.l	d4,d0
	addx	d5,d0
	move	(a3,d2*2),d3
	swap	d3

	move.b	(a0,d0),d2
	add.l	d4,d0
	addx	d5,d0
	move	(a3,d2*2),d3

	move.l	d3,(a2)+
	endr

	bra.s	.leii
.lep	addq	#8,d7
	beq.w	.qw
	subq	#1,d7
.lep2	move.b	(a0,d0),d2
	add.l	d4,d0
	move	(a3,d2*2),(a2)+
	addx	d5,d0

	cmp	d6,d0
	bhs.b	.ddwq
	dbf	d7,.lep2
	bra.w	.qw
.ddwq
	move.b	AS_LoopFlag(a4),d1
	bne.b	.q
	st	AS_NoLoop(a4)
	bra.w	.ty
.q
	addq	#1,d7

	btst	#ASLoopF_PingPong,d1
	bne.s	.PingPongLoop
.NormalLoop
	bset	#ASLoopF_Looping,AS_CurrentFPOS+2(a4)

	move.l	AS_RepeatAdr(a4),a0		;loop start
	move.l	a0,AS_CurrentAdr(a4)

	moveq	#0,d1
	move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
	add.l	AS_CurrentPos(a4),d1
	sub.l	AS_Samplesize(A4),d1
	move.l	d1,AS_CurrentPos(a4)
	add.l	d1,a0

	move.l	AS_RepeatSize(a4),d6		;loop len
	move.l	d6,AS_SampleSize(a4)
	sub.l	d1,d6				;Len - Current Position
	clr	d0				;reset integer part

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT
	dbf	d7,.checkd6	;max. Samplesize is bigger >64k !!
	bra.s	.qw
.PingPongLoop
	btst	#ASLoopF_Looping,AS_CurrentFPOS+2(a4)
	beq.s	.NormalLoop

	bset	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

	move.l	AS_RepeatAdr(a4),a0		;loop start
	move.l	a0,AS_CurrentAdr(a4)

	moveq	#0,d1
	move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
	add.l	AS_CurrentPos(a4),d1
	sub.l	AS_Samplesize(A4),d1		;Übertrag über eigentliche aktuelle Länge

	move.l	AS_Repeatsize(a4),d6
	move.l	d6,AS_Samplesize(a4)
	sub.l	d1,d6
	subq.l	#1,d6
	move.l	d6,AS_CurrentPos(a4)		;aktuelle Position = Repeatsize-1-Übertrag
	add.l	d6,a0				;Aktuelle Position
	clr	d0				;reset integer part

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt_P
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT_P
	dbf	d7,.Ping_Init2
.qw
	moveq	#0,d1
	move	d0,d1
	add.l	AS_CurrentPos(a4),d1
	move.l	d1,AS_CurrentPos(a4)

	swap	d0
	move.w	d0,AS_CurrentFPOS(a4)	;Fraction Pos

	sub.l	AS_SampleSize(a4),d1
	blt.s	.u

	tst.b	AS_LoopFlag(a4)
	bne.b	.q2
	st	AS_NoLoop(a4)			; sample is not looping
	bra.b	.u

.q2	move.l	AS_RepeatSize(a4),d6		;loop len
	move.l	d6,AS_SampleSize(a4)
	move.l	AS_Repeatadr(a4),a0
	move.l	A0,AS_CurrentAdr(a4)

	move.l	d1,AS_CurrentPos(a4)

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt1
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT1
.u	rts

.ty:	moveq	#0,d0
	subq	#1,d7
	bmi.s	.fail
.lll	move	d0,(a2)+
	dbf	d7,.lll
.fail
	rts

.Ping_Init
.Ping_Init2
		neg.w	d4		;rückwärts zählen bei Mixrate < originale Samplerate 
					;in D6 übrige Länge (currentPos = Rest vom aktuellen
					;Wert bis 0)
		move.l	a1,d1
		neg.w	d1
		move.l	d1,a1
.Ping_checkd6
		cmp.l	#$7fff,d6
		bls.s	.Ping_ok
		move.l	#$7fff,d6
.Ping_ok

.Ping_leii
		subq	#8,d7
		blt.s	.Ping_lep

		move.l	a1,d1			;Anzahl zu holender Bytes bei 8 Mixdurchläufen
		add.l	d0,d1			;+ aktuelle Position, wieviele Bytes schon weg sind
		add	d6,d1			;größer als übrige Bytes ?
		ble.s	.Ping_lep		;yup

		rept	4
		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),d3
		subx	d5,d0
		swap	d3
		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),d3
		subx	d5,d0
		move.l	d3,(a2)+
		endr

		bra.w	.Ping_leii
.Ping_lep	addq	#8,d7
		beq.w	.Ping_qw
		subq	#1,d7
.Ping_lep2
		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),(a2)+
		subx	d5,d0

		move	d0,d1
		add	d6,d1
		ble.s	.Ping_ddwq

		dbf	d7,.Ping_lep2
		bra.s	.Ping_qw
.Ping_ddwq
;		move.b	AS_LoopFlag(a4),d1
;		bne.b	.q
;		st	AS_NoLoop(a4)
;		bra.w	.ty
;.q

;weil gerade rückwärts gelooped wurde, gehts nun in jedem Fall vorwärts weiter

		addq	#1,d7

		neg.w	d0		;|gespielte Länge| (für Übertrag)

		bclr	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

		move.l	AS_RepeatAdr(a4),a0		;loop start
		move.l	a0,AS_CurrentAdr(a4)

		moveq	#0,d1
		move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
		sub.l	AS_CurrentPos(a4),d1
		move.l	d1,AS_CurrentPos(a4)
		add.l	d1,a0

		move.l	AS_RepeatSize(a4),d6		;loop len
		move.l	d6,AS_SampleSize(a4)
		sub.l	d1,d6				;Len - Current Position
		clr	d0				;reset integer part

		tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
		beq.s	.Ping_noInt
		movem.l	d0-a6,-(sp)		;nur zur Sicherheit
		move.l	AS_Int(A4),a1
		move.l	4.w,a6
		jsr	_LVOCause(a6)
		movem.l	(sp)+,d0-a6		;man weiss ja nie...
.Ping_noINT
		neg.w	d4		;rückwärts zählen bei Mixrate < originale Samplerate 
					;in D6 übrige Länge (currentPos = Rest vom aktuellen
					;Wert bis 0)

		move.l	a1,d1
		neg.w	d1
		move.l	d1,a1

		dbf	d7,.checkd6	;max. Samplesize is bigger >64k !!

		swap	d0
		move	d0,AS_CurrentFPOS(a4)	;Fraction Pos
		bra.s	.Ping_U
.Ping_qw
		neg.w	d0		;|gespielte Länge| (für Übertrag)

		moveq	#0,d1
		move	d0,d1

		swap	d0
		move.w	d0,AS_CurrentFPOS(a4)	;Fraction Pos

		move.l	AS_CurrentPos(a4),d6
		sub.l	d1,d6
		move.l	d6,AS_CurrentPos(a4)
		bgt.s	.Ping_U

		bclr	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

		move.l	AS_RepeatAdr(a4),a0		;loop start
		move.l	a0,AS_CurrentAdr(a4)

		neg.l	d6
		move.l	d6,AS_CurrentPos(A4)

		move.l	AS_RepeatSize(a4),d6		;loop len
		move.l	d6,AS_SampleSize(a4)

		tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
		beq.s	.Ping_noInt1
		movem.l	d0-a6,-(sp)		;nur zur Sicherheit
		move.l	AS_Int(A4),a1
		move.l	4.w,a6
		jsr	_LVOCause(a6)
		movem.l	(sp)+,d0-a6		;man weiss ja nie...
.Ping_noINT1
.Ping_u		rts

;-------------------- 8 Bit Mixing Routine (Part2 - Add Data) ----------------
mix2:
	moveq	#0,d7
	move	#samlen*2,d7
	
;	cmp.w	#34*4,AS_Period(a4)
;	blo	.ty

	tst.w	AS_Period(a4)
	beq	.ty

	tst.b	AS_NoLoop(a4)
	bne	.ty			;noloop

	tst.b	AS_DmaBit(a4)
	beq	.ty			;noloop

	tst.l	AS_Currentadr(a4)	;pos (addr)
	bne.s	.dw

	clr.l	AS_CurrentPos(a4)
	move.l	AS_RepeatAdr(A4),AS_CurrentAdr(a4)
	beq	.ty
	move.l	AS_RepeatSize(a4),AS_SampleSize(a4)
	beq	.ty

.dw
	move.l	clock(pc),d4
	moveq	#0,d0
	move.w	AS_Period(a4),d0

	divu.l	d0,d4
	lsl.l	#8,d4
	lsl.l	#4,d4

	move.l	mrate(pc),d0
	lsr.l	#4,d0
	divu.l	d0,d4
	swap	d4

	move.l	vtabaddr(pc),a3
	moveq	#0,d0
	move	AS_LeftVolume(a4),d0
	add	d0,d0
	lsl.l	#8,d0
	add.l	d0,a3			; Position in volume table

	move.l	AS_Currentadr(a4),a0	;pos (addr)
	move.l	AS_CurrentPos(a4),d6
	add.l	d6,a0			;aktuelle Position + dem schon gespielten

	moveq	#0,d0
	move.w	AS_CurrentFPOS(a4),d0	;fpos
	swap	d0

	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d5

	move.l	d4,d1			;Counter für Zoom
	swap	d1			;count bis zum nächsten Byte
	lsl.l	#3,d1			;Mal 8 (wg. 8 * Mix)
	swap	d1			;Overflow count, also wieviele neue Bytes zu holen sind
	move.l	d1,a1

	btst	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)
	bne.w	.Ping_Init

	neg.l	d6			;
	add.l	AS_SampleSize(a4),d6	;Gesamtlänge + (- gespielte Länge)
	bpl.s	.Checkd6
	move.l	AS_SampleSize(a4),d6	;Gesamtlänge + (- gespielte Länge) = übrige Länge
	move.l	AS_Currentadr(a4),a0	;pos (addr)
.Checkd6
	cmp.l	#$7fff,d6
	bls.s	.restart
	move.l	#$7fff,d6
.restart

.leii	subq	#8,d7
	blt.s	.lep
;	bra.s	.lep			;nur testhalber enablen !

	move.l	a1,d1
	add.l	d0,d1			;+ aktuelle Position, wieviele Bytes schon weg sind
	addx	d5,d1			;+Overflow
	cmp	d6,d1			;größer als übrige Bytes ?
	bhs.s	.lep			;yup

	rept	8
	move.b	(a0,d0),d2
	move	(a3,d2*2),d3
	add.l	d4,d0
	addx	d5,d0
	add	d3,(a2)+
	endr

	bra.s	.leii
.lep	addq	#8,d7
	beq.w	.qw
	subq	#1,d7
.lep2	move.b	(a0,d0),d2
	move	(a3,d2*2),d3
	add.l	d4,d0
	addx	d5,d0
	add	d3,(a2)+
	cmp	d6,d0
	bhs.b	.ddwq
	dbf	d7,.lep2
	bra.w	.qw
.ddwq
	move.b	AS_LoopFlag(a4),d1
	bne.b	.q
	st	AS_NoLoop(a4)
	bra.w	.ty
.q
	addq	#1,d7

	btst	#ASLoopF_PingPong,d1
	bne.s	.PingPongLoop
.NormalLoop
	bset	#ASLoopF_Looping,AS_CurrentFPOS+2(a4)

	move.l	AS_RepeatAdr(a4),a0		;loop start
	move.l	a0,AS_CurrentAdr(a4)

	moveq	#0,d1
	move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
	add.l	AS_CurrentPos(a4),d1
	sub.l	AS_Samplesize(A4),d1

	move.l	d1,AS_CurrentPos(a4)
	add.l	d1,a0

	move.l	AS_RepeatSize(a4),d6		;loop len
	move.l	d6,AS_SampleSize(a4)
	sub.l	d1,d6
	clr	d0				;reset integer part

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT
	dbf	d7,.checkd6	;max. Samplesize is bigger >64k !!
	bra.s	.qw
.PingPongLoop
	btst	#ASLoopF_Looping,AS_CurrentFPOS+2(a4)
	beq.s	.NormalLoop

	bset	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

	move.l	AS_RepeatAdr(a4),a0		;loop start
	move.l	a0,AS_CurrentAdr(a4)

	moveq	#0,d1
	move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
	add.l	AS_CurrentPos(a4),d1
	sub.l	AS_Samplesize(A4),d1		;Übertrag über eigentliche aktuelle Länge

	move.l	AS_Repeatsize(a4),d6
	move.l	d6,AS_Samplesize(a4)
	sub.l	d1,d6
	subq.l	#1,d6
	move.l	d6,AS_CurrentPos(a4)		;aktuelle Position = Repeatsize-1-Übertrag
	add.l	d6,a0				;Aktuelle Position
	clr	d0				;reset integer part

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt_P
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT_P
	dbf	d7,.Ping_Init
.qw
	moveq	#0,d1
	move	d0,d1
	add.l	AS_CurrentPos(a4),d1
	move.l	d1,AS_CurrentPos(a4)

	swap	d0
	move.w	d0,AS_CurrentFPOS(a4)	;Fraction Pos

	sub.l	AS_SampleSize(a4),d1
	blt.s	.u

	tst.b	AS_LoopFlag(a4)
	bne.b	.q2
	st	AS_NoLoop(a4)			; sample is not looping
	bra.b	.u

.q2	move.l	AS_RepeatSize(a4),d6		;loop len
	move.l	d6,AS_SampleSize(a4)
	move.l	AS_Repeatadr(a4),a0
	move.l	A0,AS_CurrentAdr(a4)

	move.l	d1,AS_CurrentPos(a4)

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt1
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT1
.ty
.u	rts

.Ping_Init
		neg.w	d4		;rückwärts zählen bei Mixrate < originale Samplerate 
					;in D6 übrige Länge (currentPos = Rest vom aktuellen
					;Wert bis 0)
		move.l	a1,d1
		neg.w	d1
		move.l	d1,a1
.Ping_checkd6
		cmp.l	#$7fff,d6
		bls.s	.Ping_ok
		move.l	#$7fff,d6
.Ping_ok

.Ping_leii
		subq	#8,d7
		blt.s	.Ping_lep

		move.l	a1,d1			;Anzahl zu holender Bytes bei 8 Mixdurchläufen
		add.l	d0,d1			;+ aktuelle Position, wieviele Bytes schon weg sind
		add	d6,d1			;größer als übrige Bytes ?
		ble.s	.Ping_lep		;yup

	rept	8
	move.b	(a0,d0),d2
	add.l	d4,d0
	move	(a3,d2*2),d3
	subx	d5,d0
	add	d3,(a2)+
	endr

		bra.w	.Ping_leii
.Ping_lep	addq	#8,d7
		beq.w	.Ping_qw
		subq	#1,d7
.Ping_lep2

		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),d3
		subx	d5,d0
		add	d3,(a2)+

		move	d0,d1
		add	d6,d1
		ble.s	.Ping_ddwq

		dbf	d7,.Ping_lep2
		bra.s	.Ping_qw
.Ping_ddwq
;		move.b	AS_LoopFlag(a4),d1
;		bne.b	.q
;		st	AS_NoLoop(a4)
;		bra.w	.ty
;.q

;weil gerade rückwärts gelooped wurde, gehts nun in jedem Fall vorwärts weiter

		addq	#1,d7

		neg.w	d0		;|gespielte Länge| (für Übertrag)

		bclr	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

		move.l	AS_RepeatAdr(a4),a0		;loop start
		move.l	a0,AS_CurrentAdr(a4)

		moveq	#0,d1
		move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
		sub.l	AS_CurrentPos(a4),d1
		move.l	d1,AS_CurrentPos(a4)
		add.l	d1,a0

		move.l	AS_RepeatSize(a4),d6		;loop len
		move.l	d6,AS_SampleSize(a4)
		sub.l	d1,d6				;Len - Current Position
		clr	d0				;reset integer part

		tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
		beq.s	.Ping_noInt
		movem.l	d0-a6,-(sp)		;nur zur Sicherheit
		move.l	AS_Int(A4),a1
		move.l	4.w,a6
		jsr	_LVOCause(a6)
		movem.l	(sp)+,d0-a6		;man weiss ja nie...
.Ping_noINT
		neg.w	d4		;rückwärts zählen bei Mixrate < originale Samplerate 
					;in D6 übrige Länge (currentPos = Rest vom aktuellen
					;Wert bis 0)

		move.l	a1,d1
		neg.w	d1
		move.l	d1,a1

		dbf	d7,.checkd6	;max. Samplesize is bigger >64k !!

		swap	d0
		move	d0,AS_CurrentFPOS(a4)	;Fraction Pos
		bra.s	.Ping_U
.Ping_qw
		neg.w	d0		;|gespielte Länge| (für Übertrag)

		moveq	#0,d1
		move	d0,d1

		swap	d0
		move.w	d0,AS_CurrentFPOS(a4)	;Fraction Pos

		move.l	AS_CurrentPos(a4),d6
		sub.l	d1,d6
		move.l	d6,AS_CurrentPos(a4)
		bgt.s	.Ping_U

		bclr	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

		move.l	AS_RepeatAdr(a4),a0		;loop start
		move.l	a0,AS_CurrentAdr(a4)

		neg.l	d6
		move.l	d6,AS_CurrentPos(A4)

		move.l	AS_RepeatSize(a4),d6		;loop len
		move.l	d6,AS_SampleSize(a4)

		tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
		beq.s	.Ping_noInt1
		movem.l	d0-a6,-(sp)		;nur zur Sicherheit
		move.l	AS_Int(A4),a1
		move.l	4.w,a6
		jsr	_LVOCause(a6)
		movem.l	(sp)+,d0-a6		;man weiss ja nie...
.Ping_noINT1
.Ping_u
		rts

;-------------------- 16 Bit Mixing Routine (Part1 - Move Data) ----------------
;-------------------- currently no volume control supported  -------------------
mix16:
	moveq	#0,d7
	move	#samlen*2,d7
	
	tst.w	AS_Period(a4)
	beq	.ty

	tst.b	AS_NoLoop(a4)
	bne	.ty			;noloop

	tst.b	AS_DmaBit(a4)
	beq	.ty			;noloop

	tst.l	AS_Currentadr(a4)	;pos (addr)
	beq	.ty

.dw	move.l	clock(pc),d4			;14187580
	moveq	#0,d0
	move.w	AS_Period(a4),d0		;80

	divu.l	d0,d4				;
	lsl.l	#8,d4				;
	lsl.l	#4,d4				;

	move.l	mrate(pc),d0			;44100
	lsr.l	#4,d0				;
	divu.l	d0,d4				;
	swap	d4				;

	move.l	vtabaddr(pc),a3

	move.l	AS_Currentadr(a4),a0	;pos (addr)
	move.l	AS_CurrentPos(a4),d6
	add.l	d6,a0			;aktuelle Position + dem schon gespielten
	add.l	d6,a0			;*2 wg. Wortlänge

	moveq	#0,d0
	move.w	AS_CurrentFPOS(a4),d0	;fpos
	swap	d0			;nach oben

	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d5

	move.l	d4,d1			;Counter für Zoom
	swap	d1			;count bis zum nächsten Wort
	lsl.l	#3,d1			;Mal 8 (wg. 8 * Mix)
	swap	d1			;Overflow count, also wieviele neue Worte zu holen sind
	move.l	d1,a1

	btst	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)
	bne.w	.Ping_Init

	neg.l	d6			;
	move.l	AS_SampleSize(a4),d1
	lsr.l	#1,d1
	add.l	d1,d6			;Gesamtlänge + (- gespielte Länge) = übrige Länge
	bpl.s	.Checkd6
	move.l	d1,d6			;übrige Länge = max
	move.l	AS_Currentadr(a4),a0	;pos (addr)
.Checkd6
	cmp.l	#$7fff,d6
	bls.s	.restart
	move.l	#$7fff,d6
.restart
	cmp.l	#1,d4			;Source-Samplerate = Dest-Samplerate ? (plain copy)
	bne.w	.leii

	subq	#8,d6
	move.l	a0,d3
.leii_fast
	subq	#8,d7
	blt.s	.lep1
	cmp	d6,d0
	bhs.s	.lep1

	move.l	(a0),(a2)
	addq.w	#8,d0
	move.l	4(a0),4(a2)
	move.l	8(a0),8(a2)
	move.l	12(a0),12(a2)

	adda.l	#16,a0
	adda.l	#16,a2
	bra.s	.leii_fast
.lep1
	addq	#8,d6
	move.l	d3,a0
	bra.w	.lep

.leii	subq	#8,d7
	blt.s	.lep

	move.l	a1,d1
	add.l	d0,d1			;+ aktuelle Position, wieviele Bytes schon weg sind
	addx	d5,d1			;+Overflow
	cmp	d6,d1			;größer als übrige Bytes ?
	bhs.s	.lep			;yup

	rept	4
	move.w	(a0,d0*2),d2
	add.l	d4,d0
	move	(a3,d2.l*2),d3
	addx	d5,d0
	swap	d3
	move.w	(a0,d0*2),d2
	add.l	d4,d0
	move	(a3,d2.l*2),d3
	addx	d5,d0
	move.l	d3,(a2)+
	endr

	bra.s	.leii
.lep	addq	#8,d7
	beq.w	.qw
	subq	#1,d7
.lep2	move.w	(a0,d0*2),d2
	add.l	d4,d0
	move	(a3,d2.l*2),(a2)+
	addx	d5,d0

	cmp	d6,d0
	bhs.b	.ddwq
	dbf	d7,.lep2
	bra.w	.qw
.ddwq
	move.b	AS_LoopFlag(a4),d1
	bne.b	.q
	st	AS_NoLoop(a4)
	bra.w	.ty
.q
	addq	#1,d7

	btst	#ASLoopF_PingPong,d1
	bne.s	.PingPongLoop
.NormalLoop
	bset	#ASLoopF_Looping,AS_CurrentFPOS+2(a4)

	move.l	AS_RepeatAdr(a4),a0		;loop start
	move.l	a0,AS_CurrentAdr(a4)

	moveq	#0,d1
	move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
	add.l	AS_CurrentPos(a4),d1
	move.l	AS_Samplesize(A4),d6
	lsr.l	#1,d6
	sub.l	d6,d1
	bpl.s	.ok
	moveq	#0,d1
.ok
	move.l	d1,AS_CurrentPos(a4)

	add.l	d1,a0
	add.l	d1,a0

	move.l	AS_RepeatSize(a4),d6		;loop len
	move.l	d6,AS_SampleSize(a4)
	lsr.l	#1,d6
	sub.l	d1,d6				;Len - Current Position
	clr	d0				;reset integer part

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT
	dbf	d7,.checkd6	;max. Samplesize is bigger >64k !!
	bra.s	.qw
.PingPongLoop
	btst	#ASLoopF_Looping,AS_CurrentFPOS+2(a4)
	beq.s	.NormalLoop

	bset	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

	move.l	AS_RepeatAdr(a4),a0		;loop start
	move.l	a0,AS_CurrentAdr(a4)

	moveq	#0,d1
	move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
	add.l	AS_CurrentPos(a4),d1
	sub.l	AS_Samplesize(A4),d1		;Übertrag über eigentliche aktuelle Länge

	move.l	AS_Repeatsize(a4),d6
	move.l	d6,AS_Samplesize(a4)
	sub.l	d1,d6
	subq.l	#1,d6
	move.l	d6,AS_CurrentPos(a4)		;aktuelle Position = Repeatsize-1-Übertrag
	add.l	d6,a0				;Aktuelle Position
	clr	d0				;reset integer part

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt_P
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT_P
	dbf	d7,.Ping_Init2
.qw
	moveq	#0,d1
	move	d0,d1
	add.l	AS_CurrentPos(a4),d1
	move.l	d1,AS_CurrentPos(a4)

	swap	d0
	move.w	d0,AS_CurrentFPOS(a4)	;Fraction Pos

	move.l	AS_Samplesize(A4),d6
	lsr.l	#1,d6
	sub.l	d6,d1
	blt.s	.u

	tst.b	AS_LoopFlag(a4)
	bne.b	.q2
	st	AS_NoLoop(a4)			; sample is not looping
	bra.b	.u

.q2	move.l	AS_RepeatSize(a4),d6		;loop len
	move.l	d6,AS_SampleSize(a4)
	move.l	AS_Repeatadr(a4),a0
	move.l	A0,AS_CurrentAdr(a4)

	move.l	d1,AS_CurrentPos(a4)

	tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
	beq.s	.noInt1
	movem.l	d0-a6,-(sp)		;nur zur Sicherheit
	move.l	AS_Int(A4),a1
	move.l	4.w,a6
	jsr	_LVOCause(a6)
	movem.l	(sp)+,d0-a6		;man weiss ja nie...
.noINT1
.u	rts

.ty:	moveq	#0,d0
	subq	#1,d7
	bmi.s	.fail
.lll	move	d0,(a2)+
	dbf	d7,.lll
.fail
	rts

.Ping_Init
.Ping_Init2
		neg.w	d4		;rückwärts zählen bei Mixrate < originale Samplerate 
					;in D6 übrige Länge (currentPos = Rest vom aktuellen
					;Wert bis 0)
		move.l	a1,d1
		neg.w	d1
		move.l	d1,a1
.Ping_checkd6
		cmp.l	#$7fff,d6
		bls.s	.Ping_ok
		move.l	#$7fff,d6
.Ping_ok

.Ping_leii
		subq	#8,d7
		blt.s	.Ping_lep

		move.l	a1,d1			;Anzahl zu holender Bytes bei 8 Mixdurchläufen
		add.l	d0,d1			;+ aktuelle Position, wieviele Bytes schon weg sind
		add	d6,d1			;größer als übrige Bytes ?
		ble.s	.Ping_lep		;yup

		rept	4
		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),d3
		subx	d5,d0
		swap	d3
		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),d3
		subx	d5,d0
		move.l	d3,(a2)+
		endr

		bra.w	.Ping_leii
.Ping_lep	addq	#8,d7
		beq.w	.Ping_qw
		subq	#1,d7
.Ping_lep2
		move.b	(a0,d0),d2
		add.l	d4,d0
		move	(a3,d2*2),(a2)+
		subx	d5,d0

		move	d0,d1
		add	d6,d1
		ble.s	.Ping_ddwq

		dbf	d7,.Ping_lep2
		bra.s	.Ping_qw
.Ping_ddwq
;		move.b	AS_LoopFlag(a4),d1
;		bne.b	.q
;		st	AS_NoLoop(a4)
;		bra.w	.ty
;.q

;weil gerade rückwärts gelooped wurde, gehts nun in jedem Fall vorwärts weiter

		addq	#1,d7

		neg.w	d0		;|gespielte Länge| (für Übertrag)

		bclr	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

		move.l	AS_RepeatAdr(a4),a0		;loop start
		move.l	a0,AS_CurrentAdr(a4)

		moveq	#0,d1
		move.w	d0,d1				;im aktuellen Rundlauf gespielte Länge
		sub.l	AS_CurrentPos(a4),d1
		move.l	d1,AS_CurrentPos(a4)
		add.l	d1,a0

		move.l	AS_RepeatSize(a4),d6		;loop len
		move.l	d6,AS_SampleSize(a4)
		sub.l	d1,d6				;Len - Current Position
		clr	d0				;reset integer part

		tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
		beq.s	.Ping_noInt
		movem.l	d0-a6,-(sp)		;nur zur Sicherheit
		move.l	AS_Int(A4),a1
		move.l	4.w,a6
		jsr	_LVOCause(a6)
		movem.l	(sp)+,d0-a6		;man weiss ja nie...
.Ping_noINT
		neg.w	d4		;rückwärts zählen bei Mixrate < originale Samplerate 
					;in D6 übrige Länge (currentPos = Rest vom aktuellen
					;Wert bis 0)

		move.l	a1,d1
		neg.w	d1
		move.l	d1,a1

		dbf	d7,.checkd6	;max. Samplesize is bigger >64k !!

		swap	d0
		move	d0,AS_CurrentFPOS(a4)	;Fraction Pos
		bra.s	.Ping_U
.Ping_qw
		neg.w	d0		;|gespielte Länge| (für Übertrag)

		moveq	#0,d1
		move	d0,d1

		swap	d0
		move.w	d0,AS_CurrentFPOS(a4)	;Fraction Pos

		move.l	AS_CurrentPos(a4),d6
		sub.l	d1,d6
		move.l	d6,AS_CurrentPos(a4)
		bgt.s	.Ping_U

		bclr	#ASLoopF_BackLooping,AS_CurrentFPOS+2(a4)

		move.l	AS_RepeatAdr(a4),a0		;loop start
		move.l	a0,AS_CurrentAdr(a4)

		neg.l	d6
		move.l	d6,AS_CurrentPos(A4)

		move.l	AS_RepeatSize(a4),d6		;loop len
		move.l	d6,AS_SampleSize(a4)

		tst.l	AS_Int(a4)		;"Interrupt" bei neuem Sample ?
		beq.s	.Ping_noInt1
		movem.l	d0-a6,-(sp)		;nur zur Sicherheit
		move.l	AS_Int(A4),a1
		move.l	4.w,a6
		jsr	_LVOCause(a6)
		movem.l	(sp)+,d0-a6		;man weiss ja nie...
.Ping_noINT1
.Ping_u		rts

;-------------------------------- für Stereo 16 Bit ----------------------------------------
;a0 = Quelladresse der gemixten Daten links
;a1 = Quelladresse der gemixten Daten rechts
;a2 = Zieladresse
;
copybufStereo:
	move	#Samlen*2/2-1,d7	;/2 da jeweils 2 Wertepaare gleichzeitig abgehandelt werden

	move.l	buff16l(pc),a3
	move.l	buff16r(pc),a4
	add.l	#32768*2,a3		;in Mitte der Tab positionieren
	add.l	#32768*2,a4		;in Mitte der Tab positionieren
.ldd3
	movem.w	(a0)+,d0/d1		;Links
	movem.w	(a1)+,d2/d3		;Rechts
	move	(a3,d0.w*2),d4
	move	(a3,d1.w*2),d5
	move	(a4,d2.w*2),d6
	move	(a4,d3.w*2),d0
	move	d4,(a2)
	move	d5,4(a2)
	move	d6,2(a2)
	move	d0,6(a2)
	addq.l	#8,a2
	dbf	d7,.ldd3
	rts

;------------------------- für Mono 16 Bit -----------------------------------------
;a0 = Quelladresse der gemixten Daten links
;a1 = Quelladresse der gemixten Daten rechts
;a2 = Zieladresse
;
copybufMono:
;	move	#$f0f,$dff180
	
	move	#Samlen*2/2-1,d7	;/2 da jeweils 2 Wertepaare gleichzeitig abgehandelt werden

	move.l	buff16l(pc),a3		;
	move.l	buff16r(pc),a4		;
	move.l	buff16effl(pc),a5	;
	move.l	buff16effr(pc),a6	;
	move.l	#32768*2,d0
	add.l	d0,a3		;in Mitte der Tab positionieren
	add.l	d0,a4		;in Mitte der Tab positionieren
	add.l	d0,a5		;in Mitte der Tab positionieren
	add.l	d0,a6		;in Mitte der Tab positionieren
.ldd3
	movem.w	(a0)+,d0/d1		;Links
	movem.w	(a1)+,d2/d3		;Rechts

	move	(a3,d0.w*2),d4
	move	(a3,d1.w*2),d5
	add	(a5,d2.w*2),d4
	add	(a5,d3.w*2),d5
	swap	d4
	swap	d5
	move	(a4,d2.w*2),d4
	move	(a4,d3.w*2),d5
	add	(a6,d0.w*2),d4
	add	(a6,d1.w*2),d5
	move.l	d4,(a2)+
	move.l	d5,(a2)+
	dbf	d7,.ldd3
	rts

;------------------------- für Surround 16 Bit -----------------------------------------
;a0 = Quelladresse der gemixten Daten links
;a1 = Quelladresse der gemixten Daten rechts
;a2 = Zieladresse
;
copybufSurround:
	move	prefetch(pc),d0		;Verzögerung in Bytes
	add	d0,d0			;-> Verzögerung in Worten
	lea	SurroundBufferL,a5
	lea	SurroundBufferR,a6
	lea	(a5,d0),a5
	lea	(a6,d0),a6

	move.l	buff16effl(pc),a3	;Surround-Tabelle L
	move.l	buff16effr(pc),a4	;Surround-Tabelle R
	add.l	#32768*2,a3		;in Mitte der Tab positionieren
	add.l	#32768*2,a4		;in Mitte der Tab positionieren

	;1. Schritt: Verzögerungspuffer an entsprechender Stelle füllen
	movem.l	a0/a1,-(sp)

	move.w	#samlen*2-1,d7
	sub	prefetch(pc),d7		;restliche Daten aus aktuellem Strom holen
firstbytes$
	move.w	(a0)+,d0		;aktuelle Daten Links
	move.w	(a1)+,d2		;aktuelle Daten Rechts
	move	(a4,d0.w*2),(a5)+	;links Lautstärke korrigieren
	move	(a3,d2.w*2),(a6)+	;rechts Lautstärke korrigieren
	dbf	d7,firstbytes$

	;2. Schritt: aktuelle Daten umwandeln und verzögerten Kram einrechnen
	movem.l	(sp),a0/a1

	move	#Samlen*2-1,d7

	move.l	buff16l(pc),a3
	move.l	buff16r(pc),a4
	add.l	#32768*2,a3		;in Mitte positionieren
	add.l	#32768*2,a4		;in Mitte positionieren
	lea	SurroundBufferL,a5
	lea	SurroundBufferR,a6
.ldd3
	move	(a0)+,d0		;links
	move	(a3,d0.w*2),d0
	sub	(a6)+,d0		;Surroundsignal links vom rechten Kanal kommend
	swap	d0
	move	(a1)+,d0		;rechts
	move	(a4,d0.w*2),d0
	sub	(a5)+,d0		;Surroundsignal rechts
	move.l	d0,(a2)+
	dbf	d7,.ldd3

	;3. Schritt: Daten für nächsten Durchlauf vorbereiten
	movem.l	(sp)+,a0/a1


	move	#Samlen*2*2,d1
	move	prefetch(pc),d0		;Verzögerung in Bytes
	add	d0,d0			;-> Verzögerung in Worten
	sub	d0,d1
	lea	(a0,d1),a0
	lea	(a1,d1),a1

	move.l	buff16effl(pc),a3	;Surround-Tabelle L
	move.l	buff16effr(pc),a4	;Surround-Tabelle R
	add.l	#32768*2,a3		;in Mitte der Tab positionieren
	add.l	#32768*2,a4		;in Mitte der Tab positionieren

	lea	SurroundBufferL,a5
	lea	SurroundBufferR,a6

	move	prefetch(pc),d7		;Verzögerung in Bytes
	subq	#1,d7
laststep$
	move.w	(a0)+,d0		;aktuelle Daten Links
	move.w	(a1)+,d2		;aktuelle Daten Rechts
	move	(a4,d0.w*2),(a5)+	;links Lautstärke korrigieren
	move	(a3,d2.w*2),(a6)+	;rechts Lautstärke korrigieren
	dbf	d7,laststep$
	rts
;------------------------ langsame aber überschaubare Testroutine -----------------------
copybufStereoold:
	move	#Samlen*2-1,d7

	move.l	buff16l(pc),a3
	move.l	buff16r(pc),a4
	add.l	#32768*2,a3		;in Mitte positionieren
	add.l	#32768*2,a4		;in Mitte positionieren
.ldd3
	move	(a0)+,d0		;links
	move	(a3,d0.w*2),d0
	swap	d0
	move	(a1)+,d0		;rechts
	move	(a4,d0.w*2),d0
	move.l	d0,(a2)+
	dbf	d7,.ldd3
	rts

;------------------------ für Surround  8 Bit ---------------------------
;
XXXXXXcopybufSurround:
	ifne	benchmark
	move	#$0f0,$dff180
	endc

	lea	divtabs,a2
	move	chans,d0
	lsl	#2,d0
	move.l	-4(a2,d0),a2

	move	prefetch(pc),d7
	lsr	#2,d7

	move.w	#samlen/4-1,d6
	sub.w	d7,d6

	subq.w	#1,d7
	move.w	d7,d0

	push	a3
.pref
	movem.l	(a3)+,d1/d3
	movem.l	d1/d3,(a4)
	movem.l	d1/d3,(a6)
	addq.l	#8,a4
	addq.l	#8,a6
	dbf	d7,.pref

	pop	a3

.ldd3
	movem.w	(a0)+,d1/d3/d4/d5
	move.b	(a2,d1),d2
	lsl	#8,d2
	move.b	(a2,d3),d2
	swap	d2
	move.b	(a2,d4),d2
	lsl	#8,d2
	move.b	(a2,d5),d2

	move.l	d2,(a1)+
	move.l	d2,(a5)+
	not.l	d2
	move.l	d2,(a4)+
	move.l	d2,(a6)+

	movem.w	(a0)+,d1/d3/d4/d5
	move.b	(a2,d1),d2
	lsl	#8,d2
	move.b	(a2,d3),d2
	swap	d2
	move.b	(a2,d4),d2
	lsl	#8,d2
	move.b	(a2,d5),d2

	move.l	d2,(a1)+
	move.l	d2,(a5)+
	not.l	d2
	move.l	d2,(a4)+
	move.l	d2,(a6)+
	dbf	d6,.ldd3

.pref2
	movem.w	(a0)+,d1/d3/d4/d5/d6/d7
	move.b	(a2,d1),d2
	lsl	#8,d2
	move.b	(a2,d3),d2
	swap	d2
	move.b	(a2,d4),d2
	lsl	#8,d2
	move.b	(a2,d5),d2

	move.l	d2,(a1)+
	move.l	d2,(a5)+
	not.l	d2
	move.l	d2,(a3)+

	movem.w	(a0)+,d1/d3
	move.b	(a2,d6),d2
	lsl	#8,d2
	move.b	(a2,d7),d2
	swap	d2
	move.b	(a2,d1),d2
	lsl	#8,d2
	move.b	(a2,d3),d2

	move.l	d2,(a1)+
	move.l	d2,(a5)+
	not.l	d2
	move.l	d2,(a3)+
	dbf	d0,.pref2

	ifne	benchmark
	move	#$0,$dff180
	endc
	rts

	ifne	benchmark
copybufSurroundold
	move	#$f0f,$dff180

	lea	divtabs,a2
	move	chans,d0
	lsl	#2,d0
	move.l	-4(a2,d0),a2

	move	prefetch(pc),d7

	move.w	#samlen-1,d6
	sub.w	d7,d6

	subq.w	#1,d7
	move.w	d7,d0

	lea	(a3),a6
.pref
	move.w	(a6)+,(a4)+
	dbf	d7,.pref

.ldd3
	movem.w	(a0)+,d1/d3
	move.b	(a2,d1),d2
	lsl	#8,d2
	move.b	(a2,d3),d2

	move.w	d2,(a1)+
	not.w	d2
	move.w	d2,(a4)+
	dbf	d6,.ldd3

.pref2
	movem.w	(a0)+,d1/d3
	move.b	(a2,d1),d2
	lsl	#8,d2
	move.b	(a2,d3),d2

	move.w	d2,(a1)+
	not.w	d2
	move.w	d2,(a3)+
	dbf	d0,.pref2

	move	#$0,$dff180
	rts
	endc
;*****************************************************************************
;*                        Daten und Initialisierungen                        *
;*****************************************************************************
dectable:
	dc.l	1,10,100,1000,10000,100000,1000000,10000000,100000000

int:	dc.b	`intuition.library`,0

toccata_name:	dc.b	`toccata.library`,0

	ifne	V37Gadtools
gad:	dc.b	`gadtools13.library`,0
	else
gad:	dc.b	`gadtools.library`,0
	endc

dos:	dc.b	`dos.library`,0
graf	dc.b	`graphics.library`,0

NoportMessage:	dc.b	`Cannot find EaglePlayer Port`,0
	even
portname:	dc.b	`EAGLEPLAYERPORT`,0

	even
	Project0WindowTags:
Project0L:
	DC.L	WA_Left,0
Project0T:
	DC.L	WA_Top,0
Project0W:
	DC.L	WA_Width,0
Project0H:
	DC.L	WA_Height,0

	DC.L	WA_IDCMP,IDCMP_Changewindow!IDCMP_RawKey!IDCMP_Menupick!LISTVIEWIDCMP!BUTTONIDCMP!IDCMP_CLOSEWINDOW!IDCMP_REFRESHWINDOW
	DC.L	WA_Flags,WFLG_DRAGBAR!WFLG_DEPTHGADGET!WFLG_CLOSEGADGET!WFLG_SMART_REFRESH

	DC.L	WA_Title,Project0WTitle
	DC.L	WA_ScreenTitle,Project0STitle
	dc.l	wa_newlookmenus,1
	dc.l	wa_autoadjust,1

	dc.l	wa_pubscreen
Pubadr
	dc.l	0
	dc.l	WA_Zoom
	dc.l	ZoomStruct
	DC.L	TAG_DONE,0
ZoomStruct
	dc.w	0,0,150,0

Ahawidth
	dc.l	399
Ahaheight
	dc.l	80

IR:
	DC.L	GT_VisualInfo,$00000000,GTBB_recessed,0
	dc.l	TAG_DONE
MTags0:
	DC.L	GTMN_Newlookmenus,1
	dc.l	TAG_DONE

TopazName:
	DC.B	'topaz.font',0

;--------------------------- spezifische Texte und Strukturen --------------------

MyAnalyzername:		dc.b	`E_Toccata_AMP.1`,0
MyUsername:		dc.b	`Toccata-Amplifier`,0
myBuggsname:		dc.b	`Buggs of Defect`,0

CallBackIntName1:	dc.b	`Toccata Amplifier Interrupt`,0

msg_Toccatalib		dc.b	'no Hardware found, please check your',10
			dc.b	'Library and your Toccata, Melody or ',10
			dc.b	'prelude soundcard if properly installed.',10
			dc.b	0
msg_Starterror		dc.b	'Unable to start playing.',0

my_easygadget:	dc.b	`   OK   `,0
my_easygadget2	dc.b	`Retry|Cancel`,0

myinfo		dc.b	`This Amplifier supports `
		dc.b	`up to 32 voices using the `
		dc.b	`toccata.library (Toccata, Melody and Prelude Soundboards). `
		dc.b	`It allows to change the `
		dc.b	`stereo bandwidth from mono `
		dc.b	`to surround for much better `
		dc.b	`sound in critical rooms and `
		dc.b	`especially when using head- `
		dc.b	`phones. `,10
		dc.b	`This program allows to `
		dc.b	`change the parameters for `
		dc.b	`surround settings, volume boost and surround delay `
		dc.b	`in realtime.`,10
		dc.b	`Version `
		ver
		dc.b	` `,10
		dc.b	`Written by Buggs of Defect. `
		dc.b	`The mixing routine is based `
		dc.b	`on the "PS3M" code written `
		dc.b	`and © by Jarno Paananen,all `
		dc.b	`optimizations & extensions`
		dc.b	`© Henryk "Buggs" Richter.`,0

my_easytitle:	dc.b	`Toccata Amplifier Message`,0

Aboutmessage:	dc.b	`     Eagleplayer Toccata Amplifier`
		ver
		dc.b	10,10
		dc.b	`            © 1997 Buggs of DEFECT`,10
		dc.b	`Contact Me At :`,10
		dc.b	`                  Henryk Richter`,10
		dc.b	`             Stephan-Jantzen-Ring  47`,10
		dc.b	`                  18106  Rostock`,10
		dc.b	`                     Germany`,10,10
		dc.b	`      EMAIL: tfa652@cks1.rz.uni-rostock.de`,10,10,0

Project0WTitle:
	dc.b	'Toccata Amplifier',0
Project0STitle:
	DC.B	'Toccata Amplifier, © DEFECT Softworks',0
	even

NumVBoostString:
    DC.B    '10.2',0

VoicesString:
    DC.B    '16',0

LISTVIEWText:
    DC.B    'Prefs for each number of Voices',0

SamplefreqText:
    DC.B    ' ',0

MixingSliderText:
    DC.B    'Sample mixing frequency',0

VBoostText:
    DC.B    'Volume Boost'
NullText:
    dc.b	` `,0

VoicesText:
    DC.B    'Voices',0

Gadget60Text:
    DC.B    'Mono <------- _Stereo ---> Surround',0

SurlevelText:
    DC.B    'Surround delay',0

Project0MName0:		DC.B    'Project',0
Project0MName1		dc.b	'Global',0
Project0MComm1		dc.b	'G',0
Project0MName6:		DC.B    'About',0
Project0MComm6:		DC.B    'A',0
Project0MName7:		DC.B    'Hide',0
Project0MComm7:		DC.B    'H',0
Project0MName8:		DC.B    'Quit',0
Project0MComm8:		DC.B    'Q',0
Project0MComm9:		DC.B    'M',0

Project0MName61:
    DC.B    'Settings',0

Project0MName71:
    DC.B    'Reset to Defaults',0

Project0MName81:
    DC.B    'Save Settings',0

Project0MName91:
    DC.B    'Mono Modules Mode',0

	even

Project0GTypes:
    DC.W    LISTVIEW_KIND
    DC.W    NUMBER_KIND
    DC.W    SLIDER_KIND
    DC.W    SLIDER_KIND
    DC.W    TEXT_KIND
    DC.W    TEXT_KIND
    DC.W    SLIDER_KIND
    DC.W    SLIDER_KIND

Project0NGads:
NG_Listview
    DC.W    4,14,301,48
    DC.L    LISTVIEWText,0
    DC.W    GD_LISTVIEW
    DC.L    PLACETEXT_ABOVE,0,0

NG_Samplefreqtext
    DC.W    229,97,68,14
    DC.L    SamplefreqText,0
    DC.W    GD_Samplefreq
    DC.L    0,0,0

NG_Samplefreq
    DC.W    12,99,213,10
    DC.L    MixingSliderText,0
    DC.W    GD_MixingSlider
    DC.L    PLACETEXT_ABOVE,0,0

NG_VBoost
    DC.W    66,72,182,12
    DC.L    VBoostText,0
    DC.W    GD_VBoost
    DC.L    PLACETEXT_ABOVE,0,0

NG_Voices
    DC.W    26,71,26,14
    DC.L    VoicesText,0
    DC.W    GD_Voices
    DC.L    PLACETEXT_ABOVE,0,0

NG_NumVBoost
	DC.W    257,71,36,13
	DC.L    NullText,0
	DC.W    GD_NumVBoost
	DC.L    PLACETEXT_ABOVE,0,0

NG_Playmode
	DC.W    14,130,283,9
	DC.L    Gadget60Text,0
	DC.W    GD_Playmode
	DC.L    PLACETEXT_ABOVE,0,0

NG_Surlevel
	DC.W    152,141,145,9
	DC.L    SurlevelText,0
	DC.W    GD_Surlevel
	DC.L    PLACETEXT_LEFT,0,0

myhook					;Filterhook, um zu große Fonts nicht
					;anzuzeigen
	dcb.b	mln_size,0
	dc.l	my_hook
	dc.l	0
	dc.l	0

Project0GTags:
    DC.L    GTLV_ShowSelected,0
	dc.l	GTLV_CallBack,myhook
    DC.L    TAG_DONE

    DC.L    GTNM_Number,32768
    DC.L    GTIN_MaxChars,5
    DC.L    STRINGA_Justification,GACT_STRINGCENTER
    DC.L    TAG_DONE
    DC.L    GTSL_Min,0
    DC.L    GTSL_Max
Freqslidermax:
    dc.l	5800
    DC.L    GTSL_Level,0
    DC.L    PGA_Freedom,LORIENT_HORIZ
    DC.L    GA_Immediate,1
    DC.L    GA_RelVerify,1
    DC.L    TAG_DONE
    DC.L    GTSL_Min,10
    DC.L    GTSL_Max,100
    DC.L    GTSL_Level,100
    DC.L    PGA_Freedom,LORIENT_HORIZ
    DC.L    GA_Immediate,1
    DC.L    GA_RelVerify,1
    DC.L    TAG_DONE
    DC.L    GTTX_Text,VoicesString
    DC.L    GTTX_Border,1
    DC.L    TAG_DONE
    DC.L    GTTX_Text,NumVBoostString
    DC.L    TAG_DONE
    DC.L    GTSL_Min,-64
    DC.L    GTSL_Max,64
    DC.L    PGA_Freedom,LORIENT_HORIZ
    DC.L    GA_Immediate,1
    DC.L    GA_RelVerify,1
    DC.L    GT_Underscore,'_'
    DC.L    TAG_DONE
    DC.L    PGA_Freedom,LORIENT_HORIZ
    DC.L    GA_Immediate,1
    DC.L    GA_RelVerify,1
    DC.L    GTSL_Min,0
    DC.L    GTSL_Max,Samlen/10
    DC.L    TAG_DONE


Project0NewMenu0:
    DC.B    NM_TITLE,0
    DC.L    Project0MName0
    DC.L    0
    DC.W    0
    DC.L    0,0

	DC.B	NM_ITEM,0
	DC.L	Project0MName91
	DC.L	Project0MComm9
Hiercheck_Mono
	DC.W	CHECKIT!Menutoggle
	DC.L	0,0

	DC.B    NM_ITEM,0
	DC.L    NM_BARLABEL,0
	DC.W    0
	DC.L    0,0

    DC.B    NM_ITEM,0
    DC.L    Project0MName6
    DC.L    Project0MComm6
    DC.W    0
    DC.L    0,0

    DC.B    NM_ITEM,0
    DC.L    Project0MName7
    DC.L    Project0MComm7
    DC.W    0
    DC.L    0,0

    DC.B    NM_ITEM,0
    DC.L    Project0MName8
    DC.L    Project0MComm8
    DC.W    0
    DC.L    0,0

    DC.B    NM_TITLE,0
    DC.L    Project0MName61
    DC.L    0
    DC.W    0
    DC.L    0,0

	DC.B	NM_ITEM,0
	DC.L	Project0MName1
	DC.L	Project0MComm1
Hiercheck
	DC.W	CHECKIT!Menutoggle
	DC.L	0,0

	DC.B    NM_ITEM,0
	DC.L    NM_BARLABEL,0
	DC.W    0
	DC.L    0,0

    DC.B    NM_ITEM,0
    DC.L    Project0MName71
    DC.L    0
    DC.W    0
    DC.L    0,0

    DC.B    NM_ITEM,0
    DC.L    Project0MName81
    DC.L    0
    DC.W    0
    DC.L    0,0

    DC.B    NM_END,0
    DC.L    0,0
    DC.W    0
    DC.L    0,0

TD:
    DC.L    TAG_DONE

;--------------------------------------------------------------------------------------------

	*------- Activate ------*
EP_Menu:	dc.l	EPM_Show		;Next
		dc.w	0			;Left Edge
		dc.w	0			;Verti Pos.
		dc.w	0			;Width-Size (Negationbreite)
		dc.w	10			;Hight-Size
		dc.w	$5B
		dc.l	0
		dc.l	.ActivateIText
		dc.l	0
		dc.b	0
		ds.b	7
		dc.l	0			*Kick2.04
.ActivateIText:	dc.b	0,3
		ds.w	2
		dc.w	1
		dc.l	0			*Topaz80
		dc.l	0			*Active.MSG (filled by EP)
		dc.l	0
		dc.w	EPNr_MainWindow	*EPNr_Engine
		dc.w	LNr_Active

	*------- Show-Window ------*
EPM_Show	dc.l	0 EPM_BarLabel		;Next
		dc.w	0			;Left Edge
		dc.w	0			;Verti Pos.
		dc.w	0			;Width-Size (Negationbreite)
		dc.w	10			;Hight-Size
		dc.w	$5B
		dc.l	0
		dc.l	.ShowIText
		dc.l	0
		dc.b	0
		ds.b	7
		dc.l	0			*Kick2.04
.ShowIText:	dc.b	0,3
		ds.w	2
		dc.w	1
		dc.l	0			*Topaz80
		dc.l	0			*Active.MSG (filled by EP)
		dc.l	0
		dc.w	EPNr_EngineShowState
		dc.w	LNr_Show2

;----------------- hier nun die Daten für den Mixing Player ----------------
LastBuffer	dc.l	0

OLDINT0:	dc.l	0
OLDINT1:	dc.l	0
OLDINT2:	dc.l	0
OLDINT3:	dc.l	0

mrate		dc.l	0
mixingperiod	dc.l	0
clock		dc.l	0


myAudioStruct	dc.l	0
numStructs	dc.w	0
numleft		dc.w	0
numright	dc.w	0
divtabs:	ds.l	16
LastBoost:	dc.w	0
maxchan		dc.w	0
chans		dc.w	0
modenr		dc.w	0

	;diese hier zusammen lassen
buffer0:	dc.l	0
buffer1:	dc.l	0
buffer2:	dc.l	0
buffer3:	dc.l	0
cbufad		dc.l	copybufStereo
	;---------------------------
SpecialBuffer1	dc.l	0
SpecialBuffer2	dc.l	0
mixad1		dc.l	mix
mixad2		dc.l	mix2	;mix2

Vtabaddr	dc.l	0
usedmode	dc.l	0
mydivtab	dc.l	0
mydivtabsize	dc.l	0
vtab:		dc.l	0
vtabsize:	dc.l	0
effectvol	dc.w	0
onplay		dc.b	0
waitstart	dc.b	0
prefetch	dc.w	0

tmpvol		dc.l	0
tmpvol2		dc.w	0
calcvol		ds.w	4
fformat		dc.w	0

buff16l:	dc.l	0			; Volumetable linker Kanal
buff16r:	dc.l	0			; Volumetable rechter Kanal
buff16effl:	dc.l	0
buff16effr:	dc.l	0

UsedUpsBuffer	dc.l	0
;divtab2
;a set 16
;	rept	16
;		ds.b	256*a
;a set a-1
;	endr
;Vtab		ds.b	66*256			; Volume tab size for 14 Bit
;						; for 8 Bit only ½ of this needed

tmpvolume	dc.w	0			; Zwischenspeicher, ob Lautstärkeänderung
tmpbalance	dc.w	0			; Zwischenspeicher, ob Lautstärkeänderung

;--------------------------------------------------------------------------------------------


PlayTags:
	dc.l	TT_Mode,TMODE_LINEAR_16_S
	dc.l	TT_Frequency
PlayFreq:				;wird vor dem Start richtig gesetzt
	dc.l	44100

	dc.l	TT_RawInt
	dc.l	CallBackInt

	dc.l	TT_RawBuffer1,RawBuffer1
	dc.l	TT_RawBuffer2,RawBuffer2
	dc.l	TT_BufferSize,RawSize
	dc.l	TT_RawIRQSize,512

	dc.l	TT_ErrorTask
PlayTask:
	dc.l	0

	dc.l	TT_ErrorMask
PlayMask:
	dc.l	0

	dc.l	TAG_DONE

CallBackInt:
	dc.l	0
	dc.l	0
	dc.b	NT_Interrupt
	dc.b	32			;32
	dc.l	CallBackIntName1	;Name
	dc.l	0

	ifne	secondInt

		dc.l	Intserver		;Interruptroutine1: Puffertausch
CallBackInt2:
		dc.l	0
		dc.l	0
		dc.b	NT_Interrupt
		dc.b	16			;32
		dc.l	CallBackIntName1	;Name
		dc.l	0

	endc

	dc.l	Domix			;Interruptroutine2: Mixen der Daten

FillBuffer1:	dc.l	0
FillBuffer2:	dc.l	0

;*********** Leertabellen (später im BSS-Hunk) ***********************
		section	1,BSS_p
		rsreset
datas:
RealNumGadgets	rs.w	1
MyVariable	rs.l	1
Attr		rs.l	2
msgport		rs.l	1
intsave:	rs.l	1
grafsave	rs.l	1
gadsave:	rs.l	1
Toccata_base	rs.l	1
_dos		rs.l	1
Port:		rs.l	1
Jumpadr		rs.l	1
Menuadr:	rs.l	1
mypubscreen:	rs.l	1	;aktueller Publicscreen
fonth:		rs.l	1	;Fonthöhe
;fontatt:	rs.l	1	;Fontattr Strukturadresse (entweder die des
				;Screens oder die eigene,wenn Screenfont zu
				;groß)
vi:		rs.l	1	;Visualinfo

mytags:		rs.l	10*2
mycontextgad:	rs.b	gg_sizeof	;CreateContext() braucht Zeiger auf
					;leere Gadgetstruktur !?

mygad:		rs.b	gng_sizeof	;Platz für New Gadget Struktur


Project0Gadgets:	rs.l	21
Gadgetadrs=Project0Gadgets

BufNewGad:		rs.w	4
			rs.l	2
			rs.w	1
			rs.l	3

myhoehe2:	rs.w	1
myhoehe1:	equ	myhoehe2
winwidth:	rs.w	1

Project0GList:	rs.l	1
Project0Menus:	rs.l	1
Winhandle	rs.l	1
Font:		rs.l	1
FontX:		rs.w	1
FontY:		rs.w	1
OffX:		rs.w	1
OffY:		rs.w	1
		rs.w	2

MY_Easystruct:	rs.l	1	;EASY-Request
		rs.l	1
		rs.l	1
		rs.l	1
		rs.l	1
temp1		rs.l	128
temp2		rs.l	128
temp:		rs.l	1

refreshflag	rs.b	1
counter		rs.b	1		;Frei
topazused	rs.b	1
modeid		rs.b	1

;an_structadr	rs.l	1
Mytask		rs.l	1
MySignal	rs.l	1
My2ndSignal	rs.l	1
immernull	rs.l	1
myobject	rs.l	1
merkpos		rs.l	1
currpos		rs.l	1
visible		rs.l	1
myplayertaglist	rs.l	1
maxtextwidth	rs.w	1
maxvisible	rs.w	1
SaveString	rs.l	1
myfontatt:	rs.l	1
		rs.w	2

MsgPort1:	rs.b	mp_size	;extra Messageport

micros		rs.l	1
seconds		rs.l	1
merk_seconds	rs.l	1
lasttime	rs.l	1
messagesent	rs.b	1
messagesent2	rs.b	1
savemodnr	rs.l	1
word7		rs.w	1	;Wort für Absturz bei Modifikation
counter2	rs.w	1
onsysfont	rs.b	1
exg		rs.b	1
onglobal	rs.b	1
toccatafound	rs.b	1	;Board vorhanden ?
MyRastport	rs.b	rp_sizeof
fontadr		rs.l	1
onmixingslider	rs.b	1
onvboostslider	rs.b	1
onPlaymodeslider	rs.b	1
onSurlevslider		rs.b	1

NumVoc		rs.l	1	;"12"
numboo		rs.l	1	;"10.1 "
		rs.w	1

SelectedL:	rs.w	1		;die zwei gehören zusammen
SelectedW:	rs.w	1		;-------------------------
Currentnumvoc	rs.w	1

List:		rs.b	lh_size
Nodes:		rs.b	ML_Sizeof*32		;max. 32 voices

ConfigDatas	rs.b	0

Prefslist	rs.w	5*32		;mixingrate.l
					;Vboost.w
					;Effect.w  StereoBasisbreite.b
					;          Surround Level.b
					;
					;Flags.w (Bit0=disable)

ConfigDatasEND	rs.b	0

;----------------------------------------------------------------------------------

;Playerbezogen
Freqlist:	rs.l	25		;max. 25 Abspielfrequenzen anbieten
Numfreq:	rs.l	1		;Anzahl der gefundenen Abspielfrequenzen
;Usedfreq:	rs.l	1		;momentan eingestellte Abspielfrequenz,
;					;def: irgendwo in der Mitte


	ifne	debug
saveusernr	rs.w	1
	endc
DatasLen:	rs.w	0
		ds.b	DatasLen


	section	3,bss_p

RawBuffer1:	ds.b	RawSize		;diese beiden Zeilen nicht auseinanderreissen !
RawBuffer2:	ds.b	RawSize		;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
EndRawBuffer:

MyUPSStruct	ds.b	UPS_Sizeof

StartBSSBuffer
MixBuffer1:	ds.l	1
MixBuffer2:	ds.l	1
MixBufferPos:	ds.l	1

SurroundBufferL:	ds.b	samlen*2*2*2
SurroundBufferR:	ds.b	samlen*2*2*2

TempBuffer	ds.b	samlen*2*2+8
TempBuffer2	ds.b	samlen*2*2+8

MixingBuffer1:	ds.w	samlen*2*2	;Puffer, die von der Mixroutine zyklisch
MixingBuffer2:	ds.w	samlen*2*2	;gefüllt werden, so daß die Länge, mit der
					;die Toccata.lib arbeitet egal wird...

UPSBuffer0a:	ds.b	SamLen*2*NumChipBuffers	;selbe Längen und Offsets wie Buffer0a...3a
		ds.w	2
UPSBuffer1a:	ds.b	SamLen*2*NumChipBuffers
		ds.w	2
Security	ds.b	20

EndBSSBuffer
Extra_AS	ds.b	AS_Sizeof*32
;bla		ds.b	200000
	end
