
**	JustPlay 1.0
**
**	$VER: justplay.s (03/08/94)
**
** 	written by Grzegorz Calkowski
**
** 	(C) Copyright 1994 The Beet Research


;==============================================================================

		incdir	"include:"

		include	"exec/exec.i"		
		include	"dos/dos.i"
		include	"dos/dosextens.i"
		include	"devices/audio.i"
		include	"workbench/workbench.i"
		include	"workbench/startup.i"
		include	"libraries/xpk.i"

		include	"lvo30/exec_lib.i"
		include	"lvo30/dos_lib.i"
		include	"lvo30/intuition_lib.i"
		include	"lvo30/icon_lib.i"
		include	"lvo30/wb_lib.i"

		include	"gcmacros.i"

;==============================================================================

VeryBegin	bra	Begin
		dc.b	"$VER: JustPlay v1.0 by TBR (03/08/94)",0
		even

;==============================================================================

Begin		movem.l	d0-a6,-(sp)

		setexec
		cmp	#36,LIB_VERSION(a6)
		bhi.s	.kickok
		st	KickFlag

.kickok		cla	a1
		call	FindTask		; get our task
		move.l	d0,a4
		tst.l	pr_CLI(a4)		; start from cli?
		bne	NoCLIAllowed

		lea	pr_MsgPort(a4),a0	; get the port
		call	WaitPort
		lea	pr_MsgPort(a4),a0
		call	GetMsg
		move.l	d0,WBMsg		; store the message

		tst.b	KickFlag
		bne	TooOldKick
		
;==============================================================================

		setexec
		openlib	DOSName
		move.l	d0,_DOSBase
		beq	Exit
		openlib	IntName
		move.l	d0,_IntuitionBase
		beq	CloseLibs
		openlib	IconName
		move.l	d0,_IconBase
		beq	CloseLibs
		openlib	WBName
		move.l	d0,_WBBase
		beq	CloseLibs

;==============================================================================

		moveq	#DOS_FIB,d1
		cld	d2
		call	AllocDosObject,DOS
		move.l	d0,FIB
		beq	CloseLibs

		call	CreateMsgPort		; create msgport for audio
		move.l	d0,AudioPort
		beq	CleanUp
		
		move.l	d0,a0
		move.l	#ioa_SIZEOF,d0		; size of AudioIO
		call	CreateIORequest
		move.l	d0,IORequest
		beq	CleanUp
		move.l	d0,a1

		move.l	#Channels,ioa_Data(a1)
		move.l	#1,ioa_Length(a1)		
		move	#0,ioa_AllocKey(a1)
		move.b	#127,LN_PRI(a1)		
		lea	AudioDevName(pc),a0
		cld	d0
		cld	d1		
		call	OpenDevice
		tst.l	d0
		beq.s	.audiookay

		cla	a0
		cla	a2
		cla	a3
		lea	CantOpenAd_es(pc),a1
		cmp.l	#ADIOERR_ALLOCFAILED,d0
		bne.s	.cantopenatall
		lea	ChAlloc_es(pc),a1
.cantopenatall	call	EasyRequestArgs,Intuition
		cmp.l	#1,d0
		beq.s	.audiookay
		bra	CleanUp

.audiookay	bsr	setciaint
		tst.l	ciaabase
		bne.s	.ciaokay
		cla	a0
		cla	a2
		cla	a3
		lea	NoInt_es(pc),a1
		call	EasyRequestArgs,Intuition
		bra	CleanUp

;==============================================================================

.ciaokay	setbase	DOS
		move.l	WBMsg(pc),a2
		cmp.l	#2,sm_NumArgs(a2)
		beq.s	.gotarg
		bhi.s	.noextsel
		cla	a0
		cla	a2
		cla	a3
		lea	NoArg_es(pc),a1
		call	EasyRequestArgs,Intuition
		bra	CleanUp
.noextsel	move.l	a2,-(sp)
		cla	a0
		cla	a2
		cla	a3
		lea	NoExtSel_es(pc),a1
		call	EasyRequestArgs,Intuition
		move.l	(sp)+,a2
.gotarg		move.l	sm_ArgList(a2),a2
		move.l	wa_Lock(a2),d1
		call	CurrentDir
		move.l	wa_Name(a2),a0
		setbase	Icon
		call	GetDiskObject
		move.l	d0,DiskObj
		bne.s	.goticon
		st	ButFlag
		bra	.getarg
.goticon	move.l	d0,a0
		move.l	do_ToolTypes(a0),a0
		move.l	a0,a5
		lea	DMAWAIT_tt(pc),a1
		call	FindToolType
		tst.l	d0
		beq.s	.nodmawait
		move.l	d0,d1
		move.l	#TmpVal,d2
		call	StrToLong,DOS
		tst.l	d0
		bmi.s	.nodmawait
		tst.l	TmpVal
		beq.s	.nodmawait
		move	TmpVal+2(pc),mt_dmadelay
.nodmawait	move.l	a5,a0
		lea	NOICON_tt(pc),a1
		call	FindToolType
		tst.l	d0
		beq.s	.yes_icon
		st	ButFlag
		bra	.getarg
.yes_icon	move.l	a5,a0
		lea	ICONTEXT_tt(pc),a1
		call	FindToolType
		tst.l	d0
		beq.s	.noicontext
		move.l	d0,IconText
.noicontext	move.l	a5,a0
		lea	ICONXPOS_tt(pc),a1
		call	FindToolType
		tst.l	d0
		beq.s	.noxpos
		move.l	d0,d1
		move.l	#TmpVal,d2
		call	StrToLong,DOS
		tst.l	d0
		bmi.s	.noxpos
		tst.l	TmpVal
		beq.s	.noxpos
		move.l	TmpVal(pc),IconXPos
.noxpos		move.l	a5,a0
		lea	ICONYPOS_tt(pc),a1
		call	FindToolType
		tst.l	d0
		beq.s	.getarg
		move.l	d0,d1
		move.l	#TmpVal,d2
		call	StrToLong,DOS
		tst.l	d0
		bmi.s	.getarg
		tst.l	TmpVal
		beq.s	.getarg
		move.l	TmpVal(pc),IconYPos
.getarg		setbase	DOS
		addq.l	#8,a2
		move.l	wa_Lock(a2),d1
		call	CurrentDir
		move.l	wa_Name(a2),d1
		move.l	d1,FName
		move.l	#ACCESS_READ,d2
		call 	Lock
		move.l	d0,FLock
		bne.s	.locked
		bsr	CantRead
		bra	CleanUp

.locked		move.l	d0,d1
		move.l	FIB(pc),d2
		move.l	d2,a2
		call	Examine
		move.l	d0,d7			;save d0
		move.l	FLock(pc),d1
		call	UnLock
		tst.l	d7
		bne.s	.examok
		bsr	CantRead
		bra	CleanUp

.examok		move.l	fib_Size(a2),d0
		move.l	d0,FileSize
		moveq	#MEMF_CHIP,d1
		sys	AllocMem
		move.l	d0,FileBuf
		bne.s	.memok
		cla	a0
		cla	a2
		cla	a3
		lea	NoMem_es(pc),a1
		call	EasyRequestArgs,Intuition
		bra	CleanUp

.memok		move.l	FName(pc),d1
		move.l	#MODE_OLDFILE,d2
		call	Open
		move.l	d0,FHandle
		bne.s	.opened
		bsr	CantRead
		bra	CleanUp

.opened		move.l	d0,d1
		move.l	FileBuf(pc),d2
		move.l	#512*3,d3
		call	Read
		tst.l	d0
		bpl.s	.read1ok
		bsr	CantRead
		move.l	FHandle(pc),d1
		call	Close	
		bra	CleanUp

.read1ok	move.l	FileBuf(pc),a0
		cmp.l	#'XPKF',(a0)
		beq.s	.xpacked
		cmp.l	#'M.K.',1080(a0)
		beq.w	.itismod
		cmp.l	#'FLT4',1080(a0)
		beq.w	.itismod
		
		cla	a0
		cla	a2
		cla	a3
		lea	NoMod_es(pc),a1
		call	EasyRequestArgs,Intuition
		tst.l	d0
		bne.w	.itismod
		move.l	FHandle(pc),d1
		call	Close
		bra	.freeit

;==============================================================================

.xpacked	move.l	FHandle(pc),d1
		call	Close
		move.l	FileBuf(pc),a1
		move.l	FileSize(pc),d0
		setexec
		call	FreeMem

		openlib	XPKName
		tst.l	d0
		beq.s	.noxpk
		move.l	d0,a6

		lea	XPK_tags(pc),a0
		move.l	FName(pc),ti_Data(a0)
		call	XpkUnpack
		move.l	d0,d7
		move.l	a6,a1
		setexec
		call	CloseLibrary
		tst.l	d7
		beq	.soplay

		cla	a0
		cla	a2
		cla	a3
		lea	XPKerr_es(pc),a1
		call	EasyRequestArgs,Intuition
		bra	CleanUp
		
.noxpk		cla	a0
		cla	a2
		cla	a3
		lea	NoXPK_es(pc),a1
		call	EasyRequestArgs,Intuition
		bra	CleanUp

;==============================================================================

.itismod	move.l	FHandle(pc),d1
		move.l	FileBuf(pc),d2
		add.l	#512*3,d2
		move.l	FileSize(pc),d3
		sub.l	#512*3,d3
		call	Read
		move.l	d0,d7
		move.l	FHandle(pc),d1
		call	Close	
		tst.l	d7
		bpl.s	.soplay
		bsr	CantRead
		bra	CleanUp

;==============================================================================

.soplay		tst.b	ButFlag
		bne	.noappicon

		sys	CreateMsgPort
		move.l	d0,AppIconPort
		beq	.noappicon
		move.l	d0,a1
		move.l	IconText(pc),a0
		move.l	DiskObj(pc),a3
		move.l	IconXPos(pc),do_CurrentX(a3)
		move.l	IconYPos(pc),do_CurrentY(a3)
		cld	d0
		cld	d1
		cla	a2
		cla	a4
		call	AddAppIconA,WB
		move.l	d0,AppIconPtr
		beq.s	.noappicon

		bsr	mt_init
		st	mt_enable
		setexec
		cld	d7			; will be "exit flag"
.waitportloop	tst.b	d7
		bne.s	.stopit
		move.l	AppIconPort(pc),a0
		call	WaitPort
.nextmsg	move.l	AppIconPort(pc),a0
		call	GetMsg
		tst.l	d0
		beq.s	.waitportloop
		move.l	d0,a1
		cmp	#MTYPE_APPICON,am_Type(a1)
		bne.s	.reply
		tst.l	am_NumArgs(a1)		
		bne.s	.getlost
		st	d7
		bra.s	.reply
.getlost	move.l	a1,d6
		cla	a0
		cla	a2
		cla	a3
		lea	GetLost_es(pc),a1
		call	EasyRequestArgs,Intuition
		move.l	d6,a1
.reply		call	ReplyMsg
		bra.s	.nextmsg
.stopit		move.l	AppIconPtr(pc),a0
		setbase	WB
		call	RemoveAppIcon
		move.l	AppIconPort(pc),a0
		setexec
		call	DeleteMsgPort
		bsr	mt_end
		bra.s	.freeit

;==============================================================================

.noappicon	bsr	mt_init
		st	mt_enable
		setbase	DOS
.clickwait	moveq	#10,d1
		call	Delay
		btst	#6,$bfe001
		bne.s	.clickwait
		btst	#2,$dff016
		bne.s	.clickwait
		bsr	mt_end

;==============================================================================

.freeit		setexec
		move.l	FileBuf(pc),a1
		move.l	FileSize(pc),d0
		call	FreeMem
		
;==============================================================================

CleanUp		tst.l	ciaabase
		beq.s	.noint
		bsr	resetciaint
.noint		move.l	DiskObj(pc),d0
		beq.s	.nodiskobj
		setbase	Icon
		move.l	d0,a0
		call	FreeDiskObject		
.nodiskobj	setexec
		move.l	IORequest(pc),d0
		beq.s	.nodev
		move.l	d0,a1
		call	CloseDevice		
.nodev		move.l	IORequest(pc),d0
		beq.s	.noioreq
		move.l	d0,a0
		call	DeleteIORequest
.noioreq	move.l	AudioPort(pc),d0
		beq.s	.nomsgport
		move.l	d0,a0
		call	DeleteMsgPort
.nomsgport	move.l	FIB(pc),d2
		beq.s	.nofib
		moveq	#DOS_FIB,d1
		call	FreeDosObject,DOS
.nofib


CloseLibs	setexec
		clslib	DOS
		clslib	Intuition
		clslib	Icon
		clslib	WB

;==============================================================================

Exit		move.l	WBMsg(pc),a1
		setexec
		call	Forbid			; NOTE! NO Permit needed!
		call	ReplyMsg
		movem.l	(sp)+,d0-a6
		moveq	#0,d0
		rts

;==============================================================================

NoCLIAllowed	openlib	DOSName
		move.l	d0,_DOSBase
		beq.s	.exit
		move.l	d0,a6		
		call	Output
		move.l	d0,d1
		beq.s	.closelib
		tst.b	KickFlag
		bne.s	.kicktooold
		move.l	#OnlyWB_msg,d2
		move.l	#OnlyWB_msg_len,d3
		bra.s	.ok
.kicktooold	move.l	#KickOld_msg,d2
		move.l	#KickOld_msg_len,d3
.ok		call 	Write
		setexec
.closelib	clslib	DOS
.exit		movem.l	(sp)+,d0-a6
		moveq	#0,d0
		rts

;==============================================================================

TooOldKick	openlib	DOSName
		move.l	d0,a6
		tst.l	d0
		beq	Exit			; no dos...
		move.l	d0,a6
		move.l	#.outwindow,d1		; we wanna window
		move.l	#MODE_NEWFILE,d2
		call	Open
		tst.l	d0			; couldn't open?
		beq.s	.clsdos
		move.l	d0,d7			; store handle in d7
		move.l	d7,d1
		move.l	#.kicktxt,d2		; text to display
		move.l	#.keybuf-.kicktxt,d3
		call	Write
		move.l	d7,d1
		move.l	#.keybuf,d2
		moveq	#1,d3
		call	Read			; read any key
		move.l	d7,d1
		call	Close
.clsdos		move.l	a6,a1
		setexec
		call	CloseLibrary
		bra	Exit
			

.outwindow	dc.b	"RAW:40/40/350/60/JustPlay v1.0",0
.kicktxt	dc.b	10,"Required at least Kickstart V37.",10,10
		dc.b	"Press any key to continue... "
.keybuf		dc.b	0
		even

;==============================================================================

CantRead	cla	a0
		cla	a2
		cla	a3
		lea	CantRead_es(pc),a1
		call	EasyRequestArgs,Intuition
		rts

;==============================================================================

_DOSBase	dc.l	0
_IntuitionBase	dc.l	0
_IconBase	dc.l	0
_WBBase		dc.l	0

WBMsg		dc.l	0
AudioPort	dc.l	0
IORequest	dc.l	0
FName		dc.l	0
FHandle		dc.l	0
FLock		dc.l	0
FIB		dc.l	0
DiskObj		dc.l	0
AppIconPtr	dc.l	0
AppIconPort	dc.l	0

FileSize	dc.l	0
FileBuf		dc.l	0

IconText	dc.l	Stop_txt
IconXPos	dc.l	NO_ICON_POSITION
IconYPos	dc.l	NO_ICON_POSITION
TmpVal		dc.l	0

XPK_tags	dc.l	XPK_InName,0
		dc.l	XPK_GetOutBuf,FileBuf
		dc.l	XPK_GetOutBufLen,FileSize
		dc.l	XPK_GetOutLen,TmpVal
		dc.l	XPK_OutMemType,MEMF_CHIP
		dc.l	TAG_DONE

Channels	dc.b	%1111
KickFlag	dc.b	0
ButFlag		dc.b	0

DOSName		dc.b	"dos.library",0
IntName		dc.b	"intuition.library",0
IconName	dc.b	"icon.library",0
WBName		dc.b	"workbench.library",0
XPKName		dc.b	"xpkmaster.library",0
AudioDevName	dc.b	"audio.device",0
		even

;==============================================================================

GetLost_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"JustPlay v1.0",10
		dc.b	"by Grzegorz Calkowski",10
		dc.b	"© 1994 The Beet Research",0
.gads		dc.b	"Nice to know",0

ChAlloc_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"Can't allocate audio channels!",0
.gads		dc.b	"Don't care|Cancel",0,0

CantOpenAd_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"Can't open audio.device!",0
.gads		dc.b	"Pity",0

NoArg_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"Requires a music module.",0
.gads		dc.b	"Sure",0

NoExtSel_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"No extended select allowed:",10
		dc.b	"Only first module will be played.",0
.gads		dc.b	"I see",0

NoMod_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"The file is NOT an ordinary module.",10
		dc.b	"Only NT/PT/STR-modules supported.",0
.gads		dc.b	"Play anyway|Cancel",0,0
		
NoInt_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"No CIA interrupt available.",0
.gads		dc.b	"Hmmm",0,0

NoMem_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"Insufficient memory.",0
.gads		dc.b	"Hard to hear",0

CantRead_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"Can't read the file!",0
.gads		dc.b	"Bye",0,0

NoXPK_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"No xpkmaster.library found.",10
		dc.b	"File can't be decrunched.",0
.gads		dc.b	"I see",0

XPKerr_es	dc.l	EasyStruct_SIZEOF,0
		dc.l	JustPlay_txt,.text,.gads
.text		dc.b	"Can't read/decrunch the file!",0
.gads		dc.b	"Bye",0

;==============================================================================

DMAWAIT_tt	dc.b	"DMAWAIT",0
NOICON_tt	dc.b	"NOICON",0
ICONTEXT_tt	dc.b	"ICONTEXT",0
ICONXPOS_tt	dc.b	"ICONXPOS",0
ICONYPOS_tt	dc.b	"ICONYPOS",0

;==============================================================================

JustPlay_txt	dc.b	"JustPlay v1.0",0
Stop_txt	dc.b	"STOP!",0


OnlyWB_msg	dc.b	"JustPlay can be used only from Workbench.",10,0
OnlyWB_msg_len	equ	*-OnlyWB_msg
KickOld_msg	dc.b	"Required at least Kickstart V37.",10,0
KickOld_msg_len	equ	*-KickOld_msg

		cnop	0,4

;==============================================================================

;**************************************************
;*    ----- Protracker V2.1A Playroutine -----    *
;* Peter "CRAYON" Hanning / Mushroom Studios 1992 *
;*    Vinterstigen 12, 14440 Ronninge, Sweden     *
;**************************************************

;---- cia interrupt ----

addicrvector	=   -6
remicrvector	=  -12
lvoopenresource	= -498
lvoopenlibrary 	= -552
lvocloselibrary	= -414
lvodelay	= -198

ciatalo = $400
ciatahi = $500
ciatblo = $600
ciatbhi = $700
ciacra  = $e00
ciacrb  = $f00

setciaint
	moveq	#2,d6
	lea	$bfd000,a5
	move.b	#'b',ciaaname+3
setcialoop
	moveq	#0,d0
	lea	ciaaname(pc),a1
	move.l	4.w,a6
	jsr	lvoopenresource(a6)
	move.l	d0,ciaabase
	beq	mt_return

	lea	gfxname(pc),a1
	moveq	#0,d0
	jsr	lvoopenlibrary(a6)
	tst.l	d0
	beq	resetciaint
	move.l	d0,a1
	move.w	206(a1),d0	; displayflags
	btst	#2,d0		; pal?
	beq.s	wasntsc
	move.l	#1773447,d7 ; pal
	bra.s	sciask
wasntsc	move.l	#1789773,d7 ; ntsc
sciask	move.l	d7,timervalue
	divu	#125,d7 ; default to normal 50 hz timer
	jsr	lvocloselibrary(a6)

	move.l	ciaabase(pc),a6
	cmp.w	#2,d6
	beq.s	trytimera
trytimerb
	lea	musicintserver(pc),a1
	moveq	#1,d0	; bit 1: timer b
	jsr	addicrvector(a6)
	move.l	#1,timerflag
	tst.l	d0
	bne.s	ciaerror
	move.l	a5,ciaaaddr
	move.b	d7,ciatblo(a5)
	lsr.w	#8,d7
	move.b	d7,ciatbhi(a5)
	bset	#0,ciacrb(a5)
	rts

trytimera
	lea	musicintserver(pc),a1
	moveq	#0,d0	; bit 0: timer a
	jsr	addicrvector(a6)
	clr.l	timerflag
	tst.l	d0
	bne.s	ciaerror
	move.l	a5,ciaaaddr
	move.b	d7,ciatalo(a5)
	lsr.w	#8,d7
	move.b	d7,ciatahi(a5)
	bset	#0,ciacra(a5)
	rts

ciaerror
	move.b	#'a',ciaaname+3
	lea	$bfe001,a5
	subq.w	#1,d6
	bne	setcialoop
	clr.l	ciaabase
	rts

resetciaint
	move.l	ciaabase(pc),d0
	beq	mt_return
	clr.l	ciaabase
	move.l	d0,a6
	move.l	ciaaaddr(pc),a5
	tst.l	timerflag
	beq.s	restimera

	bclr	#0,ciacrb(a5)
	moveq	#1,d0
	bra.s	remint

restimera
	bclr	#0,ciacra(a5)
	moveq	#0,d0
remint	lea	musicintserver(pc),a1
	moveq	#0,d0
	jsr	remicrvector(a6)
	rts

;---- tempo ----

settempo
	move.l	ciaabase(pc),d2
	beq	mt_return
	cmp.w	#32,d0
	bhs.s	setemsk
	moveq	#32,d0
setemsk	move.w	d0,realtempo
	move.l	timervalue(pc),d2
	divu	d0,d2
	move.l	ciaaaddr(pc),a4
	move.l	timerflag(pc),d0
	beq.s	settema
	move.b	d2,ciatblo(a4)
	lsr.w	#8,d2
	move.b	d2,ciatbhi(a4)
	rts

settema	move.b	d2,ciatalo(a4)
	lsr.w	#8,d2
	move.b	d2,ciatahi(a4)
	rts

realtempo	dc.w 125
ciaaaddr	dc.l 0
ciaaname	dc.b "ciaa.resource",0
ciaabase	dc.l 0
timerflag	dc.l 0
timervalue	dc.l 0
gfxname		dc.b "graphics.library",0,0

musicintserver
	dc.l 0,0
	dc.b 2,5 ; type, priority
	dc.l musintname
	dc.l 0,mt_music

musintname	dc.b "protracker musicint",0

;---- playroutine ----

n_note		equ	0  ; w
n_cmd		equ	2  ; w
n_cmdlo		equ	3  ; b
n_start		equ	4  ; l
n_length	equ	8  ; w
n_loopstart	equ	10 ; l
n_replen	equ	14 ; w
n_period	equ	16 ; w
n_finetune	equ	18 ; b
n_volume	equ	19 ; b
n_dmabit	equ	20 ; w
n_toneportdirec	equ	22 ; b
n_toneportspeed	equ	23 ; b
n_wantedperiod	equ	24 ; w
n_vibratocmd	equ	26 ; b
n_vibratopos	equ	27 ; b
n_tremolocmd	equ	28 ; b
n_tremolopos	equ	29 ; b
n_wavecontrol	equ	30 ; b
n_glissfunk	equ	31 ; b
n_sampleoffset	equ	32 ; b
n_pattpos	equ	33 ; b
n_loopcount	equ	34 ; b
n_funkoffset	equ	35 ; b
n_wavestart	equ	36 ; l
n_reallength	equ	40 ; w

mt_init	move.l	FileBuf(pc),a0
	move.l	a0,mt_songdataptr
	move.l	a0,a1
	lea	952(a1),a1
	moveq	#127,d0
	moveq	#0,d1
mtloop	move.l	d1,d2
	subq.w	#1,d0
mtloop2	move.b	(a1)+,d1
	cmp.b	d2,d1
	bgt.s	mtloop
	dbra	d0,mtloop2
	addq.b	#1,d2
			
	lea	mt_samplestarts(pc),a1
	asl.l	#8,d2
	asl.l	#2,d2
	add.l	#1084,d2
	add.l	a0,d2
	move.l	d2,a2
	moveq	#30,d0
mtloop3	clr.l	(a2)
	move.l	a2,(a1)+
	moveq	#0,d1
	move.w	42(a0),d1
	asl.l	#1,d1
	add.l	d1,a2
	add.l	#30,a0
	dbra	d0,mtloop3

	or.b	#2,$bfe001
	move.b	#6,mt_speed
	clr.b	mt_counter
	clr.b	mt_songpos
	clr.w	mt_patternpos
mt_end	sf	mt_enable
	lea	$dff000,a0
	clr.w	$a8(a0)
	clr.w	$b8(a0)
	clr.w	$c8(a0)
	clr.w	$d8(a0)
	move.w	#$f,$dff096
	rts

mt_music
	movem.l	d0-d4/a0-a6,-(sp)
	tst.b	mt_enable
	beq	mt_exit
	addq.b	#1,mt_counter
	move.b	mt_counter(pc),d0
	cmp.b	mt_speed(pc),d0
	blo.s	mt_nonewnote
	clr.b	mt_counter
	tst.b	mt_pattdeltime2
	beq.s	mt_getnewnote
	bsr.s	mt_nonewallchannels
	bra	mt_dskip

mt_nonewnote
	bsr.s	mt_nonewallchannels
	bra	mt_nonewposyet

mt_nonewallchannels
	lea	$dff0a0,a5
	lea	mt_chan1temp(pc),a6
	bsr	mt_checkefx
	lea	$dff0b0,a5
	lea	mt_chan2temp(pc),a6
	bsr	mt_checkefx
	lea	$dff0c0,a5
	lea	mt_chan3temp(pc),a6
	bsr	mt_checkefx
	lea	$dff0d0,a5
	lea	mt_chan4temp(pc),a6
	bra	mt_checkefx

mt_getnewnote
	move.l	mt_songdataptr(pc),a0
	lea	12(a0),a3
	lea	952(a0),a2	;pattpo
	lea	1084(a0),a0	;patterndata
	moveq	#0,d0
	moveq	#0,d1
	move.b	mt_songpos(pc),d0
	move.b	(a2,d0.w),d1
	asl.l	#8,d1
	asl.l	#2,d1
	add.w	mt_patternpos(pc),d1
	clr.w	mt_dmacontemp

	lea	$dff0a0,a5
	lea	mt_chan1temp(pc),a6
	bsr.s	mt_playvoice
	lea	$dff0b0,a5
	lea	mt_chan2temp(pc),a6
	bsr.s	mt_playvoice
	lea	$dff0c0,a5
	lea	mt_chan3temp(pc),a6
	bsr.s	mt_playvoice
	lea	$dff0d0,a5
	lea	mt_chan4temp(pc),a6
	bsr.s	mt_playvoice
	bra	mt_setdma

mt_playvoice
	tst.l	(a6)
	bne.s	mt_plvskip
	bsr	mt_pernop
mt_plvskip
	move.l	(a0,d1.l),(a6)
	addq.l	#4,d1
	moveq	#0,d2
	move.b	n_cmd(a6),d2
	and.b	#$f0,d2
	lsr.b	#4,d2
	move.b	(a6),d0
	and.b	#$f0,d0
	or.b	d0,d2
	tst.b	d2
	beq	mt_setregs
	moveq	#0,d3
	lea	mt_samplestarts(pc),a1
	move	d2,d4
	subq.l	#1,d2
	asl.l	#2,d2
	mulu	#30,d4
	move.l	(a1,d2.l),n_start(a6)
	move.w	(a3,d4.l),n_length(a6)
	move.w	(a3,d4.l),n_reallength(a6)
	move.b	2(a3,d4.l),n_finetune(a6)
	move.b	3(a3,d4.l),n_volume(a6)
	move.w	4(a3,d4.l),d3 ; get repeat
	tst.w	d3
	beq.s	mt_noloop
	move.l	n_start(a6),d2	; get start
	asl.w	#1,d3
	add.l	d3,d2		; add repeat
	move.l	d2,n_loopstart(a6)
	move.l	d2,n_wavestart(a6)
	move.w	4(a3,d4.l),d0	; get repeat
	add.w	6(a3,d4.l),d0	; add replen
	move.w	d0,n_length(a6)
	move.w	6(a3,d4.l),n_replen(a6)	; save replen
	moveq	#0,d0
	move.b	n_volume(a6),d0
	move.w	d0,8(a5)	; set volume
	bra.s	mt_setregs

mt_noloop
	move.l	n_start(a6),d2
	add.l	d3,d2
	move.l	d2,n_loopstart(a6)
	move.l	d2,n_wavestart(a6)
	move.w	6(a3,d4.l),n_replen(a6)	; save replen
	moveq	#0,d0
	move.b	n_volume(a6),d0
	move.w	d0,8(a5)	; set volume
mt_setregs
	move.w	(a6),d0
	and.w	#$0fff,d0
	beq	mt_checkmoreefx	; if no note
	move.w	2(a6),d0
	and.w	#$0ff0,d0
	cmp.w	#$0e50,d0
	beq.s	mt_dosetfinetune
	move.b	2(a6),d0
	and.b	#$0f,d0
	cmp.b	#3,d0	; toneportamento
	beq.s	mt_chktoneporta
	cmp.b	#5,d0
	beq.s	mt_chktoneporta
	cmp.b	#9,d0	; sample offset
	bne.s	mt_setperiod
	bsr	mt_checkmoreefx
	bra.s	mt_setperiod

mt_dosetfinetune
	bsr	mt_setfinetune
	bra.s	mt_setperiod

mt_chktoneporta
	bsr	mt_settoneporta
	bra	mt_checkmoreefx

mt_setperiod
	movem.l	d0-d1/a0-a1,-(sp)
	move.w	(a6),d1
	and.w	#$0fff,d1
	lea	mt_periodtable(pc),a1
	moveq	#0,d0
	moveq	#36,d2
mt_ftuloop
	cmp.w	(a1,d0.w),d1
	bhs.s	mt_ftufound
	addq.l	#2,d0
	dbra	d2,mt_ftuloop
mt_ftufound
	moveq	#0,d1
	move.b	n_finetune(a6),d1
	mulu	#36*2,d1
	add.l	d1,a1
	move.w	(a1,d0.w),n_period(a6)
	movem.l	(sp)+,d0-d1/a0-a1

	move.w	2(a6),d0
	and.w	#$0ff0,d0
	cmp.w	#$0ed0,d0 ; notedelay
	beq	mt_checkmoreefx

	move.w	n_dmabit(a6),$dff096
	btst	#2,n_wavecontrol(a6)
	bne.s	mt_vibnoc
	clr.b	n_vibratopos(a6)
mt_vibnoc
	btst	#6,n_wavecontrol(a6)
	bne.s	mt_trenoc
	clr.b	n_tremolopos(a6)
mt_trenoc
	move.l	n_start(a6),(a5)	; set start
	move.w	n_length(a6),4(a5)	; set length
	move.w	n_period(a6),d0
	move.w	d0,6(a5)		; set period
	move.w	n_dmabit(a6),d0
	or.w	d0,mt_dmacontemp
	bra	mt_checkmoreefx
 
mt_setdma
	move	mt_dmadelay(pc),d0
mt_waitdma
	dbra	d0,mt_waitdma
	move.w	mt_dmacontemp(pc),d0
	or.w	#$8000,d0
	move.w	d0,$dff096
	move.w	#300,d0
mt_waitdma2
	dbra	d0,mt_waitdma2

	lea	$dff000,a5
	lea	mt_chan4temp(pc),a6
	move.l	n_loopstart(a6),$d0(a5)
	move.w	n_replen(a6),$d4(a5)
	lea	mt_chan3temp(pc),a6
	move.l	n_loopstart(a6),$c0(a5)
	move.w	n_replen(a6),$c4(a5)
	lea	mt_chan2temp(pc),a6
	move.l	n_loopstart(a6),$b0(a5)
	move.w	n_replen(a6),$b4(a5)
	lea	mt_chan1temp(pc),a6
	move.l	n_loopstart(a6),$a0(a5)
	move.w	n_replen(a6),$a4(a5)

mt_dskip
	add.w	#16,mt_patternpos
	move.b	mt_pattdeltime,d0
	beq.s	mt_dskc
	move.b	d0,mt_pattdeltime2
	clr.b	mt_pattdeltime
mt_dskc	tst.b	mt_pattdeltime2
	beq.s	mt_dska
	subq.b	#1,mt_pattdeltime2
	beq.s	mt_dska
	sub.w	#16,mt_patternpos
mt_dska	tst.b	mt_pbreakflag
	beq.s	mt_nnpysk
	sf	mt_pbreakflag
	moveq	#0,d0
	move.b	mt_pbreakpos(pc),d0
	clr.b	mt_pbreakpos
	lsl.w	#4,d0
	move.w	d0,mt_patternpos
mt_nnpysk
	cmp.w	#1024,mt_patternpos
	blo.s	mt_nonewposyet
mt_nextposition	
	moveq	#0,d0
	move.b	mt_pbreakpos(pc),d0
	lsl.w	#4,d0
	move.w	d0,mt_patternpos
	clr.b	mt_pbreakpos
	clr.b	mt_posjumpflag
	addq.b	#1,mt_songpos
	and.b	#$7f,mt_songpos
	move.b	mt_songpos(pc),d1
	move.l	mt_songdataptr(pc),a0
	cmp.b	950(a0),d1
	blo.s	mt_nonewposyet
	clr.b	mt_songpos
mt_nonewposyet	
	tst.b	mt_posjumpflag
	bne.s	mt_nextposition
mt_exit	movem.l	(sp)+,d0-d4/a0-a6
	rts

mt_checkefx
	bsr	mt_updatefunk
	move.w	n_cmd(a6),d0
	and.w	#$0fff,d0
	beq.s	mt_pernop
	move.b	n_cmd(a6),d0
	and.b	#$0f,d0
	beq.s	mt_arpeggio
	cmp.b	#1,d0
	beq	mt_portaup
	cmp.b	#2,d0
	beq	mt_portadown
	cmp.b	#3,d0
	beq	mt_toneportamento
	cmp.b	#4,d0
	beq	mt_vibrato
	cmp.b	#5,d0
	beq	mt_toneplusvolslide
	cmp.b	#6,d0
	beq	mt_vibratoplusvolslide
	cmp.b	#$e,d0
	beq	mt_e_commands
setback	move.w	n_period(a6),6(a5)
	cmp.b	#7,d0
	beq	mt_tremolo
	cmp.b	#$a,d0
	beq	mt_volumeslide
mt_return
	rts

mt_pernop
	move.w	n_period(a6),6(a5)
	rts

mt_arpeggio
	moveq	#0,d0
	move.b	mt_counter(pc),d0
	divs	#3,d0
	swap	d0
	cmp.w	#0,d0
	beq.s	mt_arpeggio2
	cmp.w	#2,d0
	beq.s	mt_arpeggio1
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	lsr.b	#4,d0
	bra.s	mt_arpeggio3

mt_arpeggio1
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#15,d0
	bra.s	mt_arpeggio3

mt_arpeggio2
	move.w	n_period(a6),d2
	bra.s	mt_arpeggio4

mt_arpeggio3
	asl.w	#1,d0
	moveq	#0,d1
	move.b	n_finetune(a6),d1
	mulu	#36*2,d1
	lea	mt_periodtable(pc),a0
	add.l	d1,a0
	moveq	#0,d1
	move.w	n_period(a6),d1
	moveq	#36,d3
mt_arploop
	move.w	(a0,d0.w),d2
	cmp.w	(a0),d1
	bhs.s	mt_arpeggio4
	addq.l	#2,a0
	dbra	d3,mt_arploop
	rts

mt_arpeggio4
	move.w	d2,6(a5)
	rts

mt_fineportaup
	tst.b	mt_counter
	bne.s	mt_return
	move.b	#$0f,mt_lowmask
mt_portaup
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	mt_lowmask(pc),d0
	move.b	#$ff,mt_lowmask
	sub.w	d0,n_period(a6)
	move.w	n_period(a6),d0
	and.w	#$0fff,d0
	cmp.w	#113,d0
	bpl.s	mt_portauskip
	and.w	#$f000,n_period(a6)
	or.w	#113,n_period(a6)
mt_portauskip
	move.w	n_period(a6),d0
	and.w	#$0fff,d0
	move.w	d0,6(a5)
	rts	
 
mt_fineportadown
	tst.b	mt_counter
	bne	mt_return
	move.b	#$0f,mt_lowmask
mt_portadown
	clr.w	d0
	move.b	n_cmdlo(a6),d0
	and.b	mt_lowmask(pc),d0
	move.b	#$ff,mt_lowmask
	add.w	d0,n_period(a6)
	move.w	n_period(a6),d0
	and.w	#$0fff,d0
	cmp.w	#856,d0
	bmi.s	mt_portadskip
	and.w	#$f000,n_period(a6)
	or.w	#856,n_period(a6)
mt_portadskip
	move.w	n_period(a6),d0
	and.w	#$0fff,d0
	move.w	d0,6(a5)
	rts

mt_settoneporta
	move.l	a0,-(sp)
	move.w	(a6),d2
	and.w	#$0fff,d2
	moveq	#0,d0
	move.b	n_finetune(a6),d0
	mulu	#37*2,d0
	lea	mt_periodtable(pc),a0
	add.l	d0,a0
	moveq	#0,d0
mt_stploop
	cmp.w	(a0,d0.w),d2
	bhs.s	mt_stpfound
	addq.w	#2,d0
	cmp.w	#37*2,d0
	blo.s	mt_stploop
	moveq	#35*2,d0
mt_stpfound
	move.b	n_finetune(a6),d2
	and.b	#8,d2
	beq.s	mt_stpgoss
	tst.w	d0
	beq.s	mt_stpgoss
	subq.w	#2,d0
mt_stpgoss
	move.w	(a0,d0.w),d2
	move.l	(sp)+,a0
	move.w	d2,n_wantedperiod(a6)
	move.w	n_period(a6),d0
	clr.b	n_toneportdirec(a6)
	cmp.w	d0,d2
	beq.s	mt_cleartoneporta
	bge	mt_return
	move.b	#1,n_toneportdirec(a6)
	rts

mt_cleartoneporta
	clr.w	n_wantedperiod(a6)
	rts

mt_toneportamento
	move.b	n_cmdlo(a6),d0
	beq.s	mt_toneportnochange
	move.b	d0,n_toneportspeed(a6)
	clr.b	n_cmdlo(a6)
mt_toneportnochange
	tst.w	n_wantedperiod(a6)
	beq	mt_return
	moveq	#0,d0
	move.b	n_toneportspeed(a6),d0
	tst.b	n_toneportdirec(a6)
	bne.s	mt_toneportaup
mt_toneportadown
	add.w	d0,n_period(a6)
	move.w	n_wantedperiod(a6),d0
	cmp.w	n_period(a6),d0
	bgt.s	mt_toneportasetper
	move.w	n_wantedperiod(a6),n_period(a6)
	clr.w	n_wantedperiod(a6)
	bra.s	mt_toneportasetper

mt_toneportaup
	sub.w	d0,n_period(a6)
	move.w	n_wantedperiod(a6),d0
	cmp.w	n_period(a6),d0
	blt.s	mt_toneportasetper
	move.w	n_wantedperiod(a6),n_period(a6)
	clr.w	n_wantedperiod(a6)

mt_toneportasetper
	move.w	n_period(a6),d2
	move.b	n_glissfunk(a6),d0
	and.b	#$0f,d0
	beq.s	mt_glissskip
	moveq	#0,d0
	move.b	n_finetune(a6),d0
	mulu	#36*2,d0
	lea	mt_periodtable(pc),a0
	add.l	d0,a0
	moveq	#0,d0
mt_glissloop
	cmp.w	(a0,d0.w),d2
	bhs.s	mt_glissfound
	addq.w	#2,d0
	cmp.w	#36*2,d0
	blo.s	mt_glissloop
	moveq	#35*2,d0
mt_glissfound
	move.w	(a0,d0.w),d2
mt_glissskip
	move.w	d2,6(a5) ; set period
	rts

mt_vibrato
	move.b	n_cmdlo(a6),d0
	beq.s	mt_vibrato2
	move.b	n_vibratocmd(a6),d2
	and.b	#$0f,d0
	beq.s	mt_vibskip
	and.b	#$f0,d2
	or.b	d0,d2
mt_vibskip
	move.b	n_cmdlo(a6),d0
	and.b	#$f0,d0
	beq.s	mt_vibskip2
	and.b	#$0f,d2
	or.b	d0,d2
mt_vibskip2
	move.b	d2,n_vibratocmd(a6)
mt_vibrato2
	move.b	n_vibratopos(a6),d0
	lea	mt_vibratotable(pc),a4
	lsr.w	#2,d0
	and.w	#$001f,d0
	moveq	#0,d2
	move.b	n_wavecontrol(a6),d2
	and.b	#$03,d2
	beq.s	mt_vib_sine
	lsl.b	#3,d0
	cmp.b	#1,d2
	beq.s	mt_vib_rampdown
	move.b	#255,d2
	bra.s	mt_vib_set
mt_vib_rampdown
	tst.b	n_vibratopos(a6)
	bpl.s	mt_vib_rampdown2
	move.b	#255,d2
	sub.b	d0,d2
	bra.s	mt_vib_set
mt_vib_rampdown2
	move.b	d0,d2
	bra.s	mt_vib_set
mt_vib_sine
	move.b	(a4,d0.w),d2
mt_vib_set
	move.b	n_vibratocmd(a6),d0
	and.w	#15,d0
	mulu	d0,d2
	lsr.w	#7,d2
	move.w	n_period(a6),d0
	tst.b	n_vibratopos(a6)
	bmi.s	mt_vibratoneg
	add.w	d2,d0
	bra.s	mt_vibrato3
mt_vibratoneg
	sub.w	d2,d0
mt_vibrato3
	move.w	d0,6(a5)
	move.b	n_vibratocmd(a6),d0
	lsr.w	#2,d0
	and.w	#$003c,d0
	add.b	d0,n_vibratopos(a6)
	rts

mt_toneplusvolslide
	bsr	mt_toneportnochange
	bra	mt_volumeslide

mt_vibratoplusvolslide
	bsr.s	mt_vibrato2
	bra	mt_volumeslide

mt_tremolo
	move.b	n_cmdlo(a6),d0
	beq.s	mt_tremolo2
	move.b	n_tremolocmd(a6),d2
	and.b	#$0f,d0
	beq.s	mt_treskip
	and.b	#$f0,d2
	or.b	d0,d2
mt_treskip
	move.b	n_cmdlo(a6),d0
	and.b	#$f0,d0
	beq.s	mt_treskip2
	and.b	#$0f,d2
	or.b	d0,d2
mt_treskip2
	move.b	d2,n_tremolocmd(a6)
mt_tremolo2
	move.b	n_tremolopos(a6),d0
	lea	mt_vibratotable(pc),a4
	lsr.w	#2,d0
	and.w	#$001f,d0
	moveq	#0,d2
	move.b	n_wavecontrol(a6),d2
	lsr.b	#4,d2
	and.b	#$03,d2
	beq.s	mt_tre_sine
	lsl.b	#3,d0
	cmp.b	#1,d2
	beq.s	mt_tre_rampdown
	move.b	#255,d2
	bra.s	mt_tre_set
mt_tre_rampdown
	tst.b	n_vibratopos(a6)
	bpl.s	mt_tre_rampdown2
	move.b	#255,d2
	sub.b	d0,d2
	bra.s	mt_tre_set
mt_tre_rampdown2
	move.b	d0,d2
	bra.s	mt_tre_set
mt_tre_sine
	move.b	(a4,d0.w),d2
mt_tre_set
	move.b	n_tremolocmd(a6),d0
	and.w	#15,d0
	mulu	d0,d2
	lsr.w	#6,d2
	moveq	#0,d0
	move.b	n_volume(a6),d0
	tst.b	n_tremolopos(a6)
	bmi.s	mt_tremoloneg
	add.w	d2,d0
	bra.s	mt_tremolo3
mt_tremoloneg
	sub.w	d2,d0
mt_tremolo3
	bpl.s	mt_tremoloskip
	clr.w	d0
mt_tremoloskip
	cmp.w	#$40,d0
	bls.s	mt_tremolook
	move.w	#$40,d0
mt_tremolook
	move.w	d0,8(a5)
	move.b	n_tremolocmd(a6),d0
	lsr.w	#2,d0
	and.w	#$003c,d0
	add.b	d0,n_tremolopos(a6)
	rts

mt_sampleoffset
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	beq.s	mt_sononew
	move.b	d0,n_sampleoffset(a6)
mt_sononew
	move.b	n_sampleoffset(a6),d0
	lsl.w	#7,d0
	cmp.w	n_length(a6),d0
	bge.s	mt_sofskip
	sub.w	d0,n_length(a6)
	lsl.w	#1,d0
	add.l	d0,n_start(a6)
	rts
mt_sofskip
	move.w	#$0001,n_length(a6)
	rts

mt_volumeslide
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	lsr.b	#4,d0
	tst.b	d0
	beq.s	mt_volslidedown
mt_volslideup
	add.b	d0,n_volume(a6)
	cmp.b	#$40,n_volume(a6)
	bmi.s	mt_vsuskip
	move.b	#$40,n_volume(a6)
mt_vsuskip
	move.b	n_volume(a6),d0
	move.w	d0,8(a5)
	rts

mt_volslidedown
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
mt_volslidedown2
	sub.b	d0,n_volume(a6)
	bpl.s	mt_vsdskip
	clr.b	n_volume(a6)
mt_vsdskip
	move.b	n_volume(a6),d0
	move.w	d0,8(a5)
	rts

mt_positionjump
	move.b	n_cmdlo(a6),d0
	subq.b	#1,d0
	move.b	d0,mt_songpos
mt_pj2	clr.b	mt_pbreakpos
	st 	mt_posjumpflag
	rts

mt_volumechange
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	cmp.b	#$40,d0
	bls.s	mt_volumeok
	moveq	#$40,d0
mt_volumeok
	move.b	d0,n_volume(a6)
	move.w	d0,8(a5)
	rts

mt_patternbreak
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	move.l	d0,d2
	lsr.b	#4,d0
	mulu	#10,d0
	and.b	#$0f,d2
	add.b	d2,d0
	cmp.b	#63,d0
	bhi.s	mt_pj2
	move.b	d0,mt_pbreakpos
	st	mt_posjumpflag
	rts

mt_setspeed
	moveq	#0,d0
	move.b	3(a6),d0
	beq	mt_end
	cmp.b	#32,d0
	bhs	settempo
	clr.b	mt_counter
	move.b	d0,mt_speed
	rts

mt_checkmoreefx
	bsr	mt_updatefunk
	move.b	2(a6),d0
	and.b	#$0f,d0
	cmp.b	#$9,d0
	beq	mt_sampleoffset
	cmp.b	#$b,d0
	beq	mt_positionjump
	cmp.b	#$d,d0
	beq.s	mt_patternbreak
	cmp.b	#$e,d0
	beq.s	mt_e_commands
	cmp.b	#$f,d0
	beq.s	mt_setspeed
	cmp.b	#$c,d0
	beq	mt_volumechange
	bra	mt_pernop

mt_e_commands
	move.b	n_cmdlo(a6),d0
	and.b	#$f0,d0
	lsr.b	#4,d0
	beq.s	mt_filteronoff
	cmp.b	#1,d0
	beq	mt_fineportaup
	cmp.b	#2,d0
	beq	mt_fineportadown
	cmp.b	#3,d0
	beq.s	mt_setglisscontrol
	cmp.b	#4,d0
	beq	mt_setvibratocontrol
	cmp.b	#5,d0
	beq	mt_setfinetune
	cmp.b	#6,d0
	beq	mt_jumploop
	cmp.b	#7,d0
	beq	mt_settremolocontrol
	cmp.b	#9,d0
	beq	mt_retrignote
	cmp.b	#$a,d0
	beq	mt_volumefineup
	cmp.b	#$b,d0
	beq	mt_volumefinedown
	cmp.b	#$c,d0
	beq	mt_notecut
	cmp.b	#$d,d0
	beq	mt_notedelay
	cmp.b	#$e,d0
	beq	mt_patterndelay
	cmp.b	#$f,d0
	beq	mt_funkit
	rts

mt_filteronoff
	move.b	n_cmdlo(a6),d0
	and.b	#1,d0
	asl.b	#1,d0
	and.b	#$fd,$bfe001
	or.b	d0,$bfe001
	rts	

mt_setglisscontrol
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	and.b	#$f0,n_glissfunk(a6)
	or.b	d0,n_glissfunk(a6)
	rts

mt_setvibratocontrol
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	and.b	#$f0,n_wavecontrol(a6)
	or.b	d0,n_wavecontrol(a6)
	rts

mt_setfinetune
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	move.b	d0,n_finetune(a6)
	rts

mt_jumploop
	tst.b	mt_counter
	bne	mt_return
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	beq.s	mt_setloop
	tst.b	n_loopcount(a6)
	beq.s	mt_jumpcnt
	subq.b	#1,n_loopcount(a6)
	beq	mt_return
mt_jmploop	move.b	n_pattpos(a6),mt_pbreakpos
	st	mt_pbreakflag
	rts

mt_jumpcnt
	move.b	d0,n_loopcount(a6)
	bra.s	mt_jmploop

mt_setloop
	move.w	mt_patternpos(pc),d0
	lsr.w	#4,d0
	move.b	d0,n_pattpos(a6)
	rts

mt_settremolocontrol
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	lsl.b	#4,d0
	and.b	#$0f,n_wavecontrol(a6)
	or.b	d0,n_wavecontrol(a6)
	rts

mt_retrignote
	move.l	d1,-(sp)
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	beq.s	mt_rtnend
	moveq	#0,d1
	move.b	mt_counter(pc),d1
	bne.s	mt_rtnskp
	move.w	(a6),d1
	and.w	#$0fff,d1
	bne.s	mt_rtnend
	moveq	#0,d1
	move.b	mt_counter(pc),d1
mt_rtnskp
	divu	d0,d1
	swap	d1
	tst.w	d1
	bne.s	mt_rtnend
mt_doretrig
	move.w	n_dmabit(a6),$dff096	; channel dma off
	move.l	n_start(a6),(a5)	; set sampledata pointer
	move.w	n_length(a6),4(a5)	; set length
	move.w	#300,d0
mt_rtnloop1
	dbra	d0,mt_rtnloop1
	move.w	n_dmabit(a6),d0
	bset	#15,d0
	move.w	d0,$dff096
	move.w	#300,d0
mt_rtnloop2
	dbra	d0,mt_rtnloop2
	move.l	n_loopstart(a6),(a5)
	move.l	n_replen(a6),4(a5)
mt_rtnend
	move.l	(sp)+,d1
	rts

mt_volumefineup
	tst.b	mt_counter
	bne	mt_return
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$f,d0
	bra	mt_volslideup

mt_volumefinedown
	tst.b	mt_counter
	bne	mt_return
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	bra	mt_volslidedown2

mt_notecut
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	cmp.b	mt_counter(pc),d0
	bne	mt_return
	clr.b	n_volume(a6)
	move.w	#0,8(a5)
	rts

mt_notedelay
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	cmp.b	mt_counter,d0
	bne	mt_return
	move.w	(a6),d0
	beq	mt_return
	move.l	d1,-(sp)
	bra	mt_doretrig

mt_patterndelay
	tst.b	mt_counter
	bne	mt_return
	moveq	#0,d0
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	tst.b	mt_pattdeltime2
	bne	mt_return
	addq.b	#1,d0
	move.b	d0,mt_pattdeltime
	rts

mt_funkit
	tst.b	mt_counter
	bne	mt_return
	move.b	n_cmdlo(a6),d0
	and.b	#$0f,d0
	lsl.b	#4,d0
	and.b	#$0f,n_glissfunk(a6)
	or.b	d0,n_glissfunk(a6)
	tst.b	d0
	beq	mt_return
mt_updatefunk
	movem.l	a0/d1,-(sp)
	moveq	#0,d0
	move.b	n_glissfunk(a6),d0
	lsr.b	#4,d0
	beq.s	mt_funkend
	lea	mt_funktable(pc),a0
	move.b	(a0,d0.w),d0
	add.b	d0,n_funkoffset(a6)
	btst	#7,n_funkoffset(a6)
	beq.s	mt_funkend
	clr.b	n_funkoffset(a6)

	move.l	n_loopstart(a6),d0
	moveq	#0,d1
	move.w	n_replen(a6),d1
	add.l	d1,d0
	add.l	d1,d0
	move.l	n_wavestart(a6),a0
	addq.l	#1,a0
	cmp.l	d0,a0
	blo.s	mt_funkok
	move.l	n_loopstart(a6),a0
mt_funkok
	move.l	a0,n_wavestart(a6)
	moveq	#-1,d0
	sub.b	(a0),d0
	move.b	d0,(a0)
mt_funkend
	movem.l	(sp)+,a0/d1
	rts


mt_funktable dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128

mt_vibratotable	
	dc.b   0, 24, 49, 74, 97,120,141,161
	dc.b 180,197,212,224,235,244,250,253
	dc.b 255,253,250,244,235,224,212,197
	dc.b 180,161,141,120, 97, 74, 49, 24

mt_periodtable
; tuning 0, normal
	dc.w	856,808,762,720,678,640,604,570,538,508,480,453
	dc.w	428,404,381,360,339,320,302,285,269,254,240,226
	dc.w	214,202,190,180,170,160,151,143,135,127,120,113
; tuning 1
	dc.w	850,802,757,715,674,637,601,567,535,505,477,450
	dc.w	425,401,379,357,337,318,300,284,268,253,239,225
	dc.w	213,201,189,179,169,159,150,142,134,126,119,113
; tuning 2
	dc.w	844,796,752,709,670,632,597,563,532,502,474,447
	dc.w	422,398,376,355,335,316,298,282,266,251,237,224
	dc.w	211,199,188,177,167,158,149,141,133,125,118,112
; tuning 3
	dc.w	838,791,746,704,665,628,592,559,528,498,470,444
	dc.w	419,395,373,352,332,314,296,280,264,249,235,222
	dc.w	209,198,187,176,166,157,148,140,132,125,118,111
; tuning 4
	dc.w	832,785,741,699,660,623,588,555,524,495,467,441
	dc.w	416,392,370,350,330,312,294,278,262,247,233,220
	dc.w	208,196,185,175,165,156,147,139,131,124,117,110
; tuning 5
	dc.w	826,779,736,694,655,619,584,551,520,491,463,437
	dc.w	413,390,368,347,328,309,292,276,260,245,232,219
	dc.w	206,195,184,174,164,155,146,138,130,123,116,109
; tuning 6
	dc.w	820,774,730,689,651,614,580,547,516,487,460,434
	dc.w	410,387,365,345,325,307,290,274,258,244,230,217
	dc.w	205,193,183,172,163,154,145,137,129,122,115,109
; tuning 7
	dc.w	814,768,725,684,646,610,575,543,513,484,457,431
	dc.w	407,384,363,342,323,305,288,272,256,242,228,216
	dc.w	204,192,181,171,161,152,144,136,128,121,114,108
; tuning -8
	dc.w	907,856,808,762,720,678,640,604,570,538,508,480
	dc.w	453,428,404,381,360,339,320,302,285,269,254,240
	dc.w	226,214,202,190,180,170,160,151,143,135,127,120
; tuning -7
	dc.w	900,850,802,757,715,675,636,601,567,535,505,477
	dc.w	450,425,401,379,357,337,318,300,284,268,253,238
	dc.w	225,212,200,189,179,169,159,150,142,134,126,119
; tuning -6
	dc.w	894,844,796,752,709,670,632,597,563,532,502,474
	dc.w	447,422,398,376,355,335,316,298,282,266,251,237
	dc.w	223,211,199,188,177,167,158,149,141,133,125,118
; tuning -5
	dc.w	887,838,791,746,704,665,628,592,559,528,498,470
	dc.w	444,419,395,373,352,332,314,296,280,264,249,235
	dc.w	222,209,198,187,176,166,157,148,140,132,125,118
; tuning -4
	dc.w	881,832,785,741,699,660,623,588,555,524,494,467
	dc.w	441,416,392,370,350,330,312,294,278,262,247,233
	dc.w	220,208,196,185,175,165,156,147,139,131,123,117
; tuning -3
	dc.w	875,826,779,736,694,655,619,584,551,520,491,463
	dc.w	437,413,390,368,347,328,309,292,276,260,245,232
	dc.w	219,206,195,184,174,164,155,146,138,130,123,116
; tuning -2
	dc.w	868,820,774,730,689,651,614,580,547,516,487,460
	dc.w	434,410,387,365,345,325,307,290,274,258,244,230
	dc.w	217,205,193,183,172,163,154,145,137,129,122,115
; tuning -1
	dc.w	862,814,768,725,684,646,610,575,543,513,484,457
	dc.w	431,407,384,363,342,323,305,288,272,256,242,228
	dc.w	216,203,192,181,171,161,152,144,136,128,121,114

mt_chan1temp	dc.l	0,0,0,0,0,$00010000,0,  0,0,0,0
mt_chan2temp	dc.l	0,0,0,0,0,$00020000,0,  0,0,0,0
mt_chan3temp	dc.l	0,0,0,0,0,$00040000,0,  0,0,0,0
mt_chan4temp	dc.l	0,0,0,0,0,$00080000,0,  0,0,0,0

mt_samplestarts	dc.l	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
		dc.l	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

mt_songdataptr	dc.l 0
mt_speed	dc.b 6
mt_counter	dc.b 0
mt_songpos	dc.b 0
mt_pbreakpos	dc.b 0
mt_posjumpflag	dc.b 0
mt_pbreakflag	dc.b 0
mt_lowmask	dc.b 0
mt_pattdeltime	dc.b 0
mt_pattdeltime2	dc.b 0
mt_enable	dc.b 0
mt_patternpos	dc.w 0
mt_dmacontemp	dc.w 0
mt_dmadelay	dc.w 600

