* MultiPlayer
* Copyright (C) 1992 Bryan Ford
*
* 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; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* I (the author of MultiPlayer) can be contacted on the Internet at
* "bryan.ford@m.cc.utah.edu".  See "Player.doc" for other addresses.
*
* This Protracker playroutine is very heavily modified from the one
* supplied with Protracker 1.1b, 1.2, and 2.1.  (All of these versions
* used the same player code.)  In particular, it uses the NotePlayer
* system to play notes instead of going to the hardware.  It also
* contains many bug fixes and compatibility enhancements (such as the
* ability to play 15-instrument modules).
*
* Note that while most previous MutantTracker play routines were
* public domain, this version is expressly taken out of the public
* domain and brought under the GNU General Public License.
*
* $Id: ptsplay.asm,v 5.5 92/09/14 18:42:54 BAF Exp $
*




; This is THE ONLY 100% FIXED VERSION of the PROTRACKER PLAYROUTINE!!!
;
; Please spread this WORLDWIDE as we are are fed up with utilities
; using the bugged playroutine supplied with the original Protracker
; release archieve.
;
; Some utils I hope to see with the 100% FIXED playroutine SOON:
;
; PTPlayer  -command by TSM/Vision
; Chameleon Music Player (ChamPlay)
; Noiseplayer by TRSI
;
; ...and all other utils playing PROTRACKER MODULES!!!
;
; ///BUG/// -*- N E T W O R K -*-
;
; Cool musicians write to: Noiseless
;                          Box 5036
;                          6021 Alesund
;                          Norway




;********************************************  ; 100% FIXED VERSION
;* ----- Protracker V1.1B Playroutine ----- *
;* Lars "Zap" Hamre/Amiga Freelancers 1991  *
;* Bekkeliveien 10, N-2010 STRØMMEN, Norway *
;********************************************

; VBlank Version 2.01:

; Call mt_init to initialize the routine, then call mt_music on
; each vertical blank (50 Hz). To end the song and turn off all
; voices, call mt_end.

; This playroutine is not very fast, optimized or well commented,
; but all the new commands in PT1.1A should work.
; If it's not good enough, you'll have to change it yourself.
; We'll try to write a faster routine soon...

; Changes from V1.0C playroutine:
; - Vibrato depth changed to be compatible with Noisetracker 2.0.
;   You'll have to double all vib. depths on old PT modules.
; - Funk Repeat changed to Invert Loop.
; - Period set back earlier when stopping an effect.



        include "exec/types.i"
        include "exec/ables.i"
        include "exec/execbase.i"
        include "hardware/custom.i"
        include "player.i"
        include "bry/macros.i"

_intena equ (CUSTOM+intena)

NoteInfo        equ     $00
NoteInit        equ     $04
NoteFinish      equ     $08
NoteStart       equ     $0c
NoteStop        equ     $10
NoteFreqVol     equ     $14
NoteFreq        equ     $18
NoteVol         equ     $1c

        xref    modmem,modend,intsongpos,intrepeat,getfreqmodspeed,hookfunc
        xref    ntgetsongname,ntgetsongauthor,intflashnote,intflashsample,intflashscroll,changetintcia
        xref    scrollmod,scrolllines,notetab,modflags,filter,modtype

        xdef    ntstart,ptfilter

        code    text

ntstart:
        ori.b   #MTF_PROTRACKER!MTF_FILTER,modtype(a4)
        plstartret 9$

        cnop    0,4
        dc.l    gmod_GetScroll+4
9$      gmodbra init                    ; InitMusic
        gmodbra start                   ; StartMusic
        gmodbra mt_stop                 ; StopMusic
        gmodbra fin                     ; EndMusic
        gmodbra noteplayersave          ; NotePlayer
        gmodq   1                       ; ContinueMusic
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodnop
        gmodbra ntgetsongname           ; GetSongName
        gmodbra ntgetsongauthor         ; GetSongAuthor
        gmodbra getfreqmodspeed         ; GetFrequency
        gmodbra mt_music                ; TimerTick
        gmodbra \makername              ; GetMakerName
        gmodbra \hook                   ; Hook
        gmodbra \jump
        gmodnop
        move.l  scroll(pc),d0
        rts

\hook
        move.l  #GMODHF_REPEAT!GMODHF_SEQUENCE,d0
        rts

\makername
        lea     name(pc),a0
        move.l  a0,d0
        rts

\jump
        DISABLE a0
        clr.w   mt_PatternPos
        clr.b   mt_PBreakPos
        clr.b   mt_PosJumpFlag
        move.L  mt_SongDataPtr(PC),A0
        suba.w  seqadj(pc),a0
        moveq   #0,d0
        move.b  $3b6(a0),d0
        cmp.l   d0,d1
        blo.s   \jumpok
        cq      d1
\jumpok
        move.b  d1,mt_SongPos
        exg     d1,d0
        jsr     intsongpos
        ENABLE  a0
        moveq   #1,d1
        rts


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
n_channelno     EQU     42 ; W
n_realper       EQU     44 ; W
n_realvol       EQU     46 ; W

noteplayersave
        move.l  a0,noteplayer
        moveq   #1,d0
        rts

init    movem.l d2-d3/a2-a3,-(sp)

        move.l  noteplayer(pc),a1       ; Initialize the NotePlayer
        sub.l   a0,a0
        moveq   #4,d0
        jsr     NoteInit(a1)
        tst.l   d0
        bnz     initout

        clr.l   scroll

        move.l  modmem,a0               ;
        MOVE.L  A0,mt_SongDataPtr
        move.l  modend,a3
        subq.l  #4,a3

        moveq   #0,d0                   ; Check for old modules
        moveq   #0,d1
        move.w  #31-1,-(sp)
        tst.b   $1d6(a0)
        beq.s   1$
        cmp.b   #1,$1f3(a0)
        beq.s   1$
        cmp.l   #'M.K.',$438(a0)
        beq.s   1$
        move.w  #$1e0,d0
        move.w  #$1e4,d1
        move.w  #15-1,(sp)
1$      move.w  d0,seqadj
        move.w  d1,blkadj

        MOVE.L  A0,A1
        LEA     952(A1),A1
        suba.w  d0,a1

        movem.l d0-d1/a0-a1,-(sp)       ; Set MultiPlayer's position display
        moveq   #0,d0
        moveq   #0,d1
        move.b  -2(a1),d1
        jsr     intsongpos
        movem.l (sp)+,d0-d1/a0-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
        suba.w  blkadj(pc),a2           ;
        move.w  (sp)+,d0
mtloop3

* Clear the first four bytes of the sample.  This piece of code has caused a great deal of grief for
* many people before it included this end-of-module check.  (Just ask Ed Mackey. :-) )  Most
* MutantTracker modules don't use all the available instrument slots, so the last instruments are
* empty (zero length).  However, in unmodified player source code, this code keeps plowing on through,
* clearing the first four bytes _past_ the end of the module.  This is usually no problem when the
* module is part of a game or demo or something, but can cause weird memory errors when the module's
* memory is allocated dynamically to its exact length.
*
* Oh yeah...Why clear the first four bytes?  Protracker and most other closely related mutants handle
* non-repeating samples by simply setting the repeat position and length so that, after the sample is
* played once, it plays the first four bytes over and over forever (until another sample is started).
* If the first four bytes weren't zero, then you'd hear a weird buzzy sound at the end of any non-
* repeating sample.
*
* Most new tracker modules come with the first four bytes of each sample already cleared, so this isn't
* necessary for them.  It's mainly for older modules.

        cmp.l   a2,a3
        blt.s   \inrange
        clr.l   (a2)
\inrange

        MOVE.L  A2,(A1)+
        MOVEQ   #0,D1
        MOVE.W  42(A0),D1
        bz.b    \nosample

* This little hack is for old-style (15-instrument) modules that occasionally had 'repeat' stored as
* number of bytes instead of words.  We assume that this is the case if repeat+replen > length.
* This should be safe for all new modules, since repeat+replen is never supposed to be bigger than
* the sample size.  However, it may not detect all cases of this syndrome, because repeat+replen
* is allowed to be smaller (even much smaller) than the sample length (i.e. when some of the sample
* is not used).
        move.w  42+4(a0),d3
        add.w   42+6(a0),d3
        cmp.w   d1,d3
        bls.b   \repeat_ok
        lsr.w   42+4(a0)
\repeat_ok


        ASL.L   #1,D1
        move.l  d1,d2
        ADD.l   d1,a2
\nosample

        ADD.L   #30,A0
        DBRA    D0,mtloop3

        addq.l  #4,a3                   ; See if the last sample is a scrolltext
        cmp.l   a2,a3
        blt.b   \noscroll
        move.l  d2,d0
        cq      d1
\more
        tst.b   -(a2)
        bpl.b   \lower
        addq.l  #1,d1
\lower
        subq.l  #1,d0
        bhi.b   \more

        lsl.l   #2,d1                   ; If 3/4 or more of the bytes are <$80, assume it's ASCII
        cmp.l   d1,d2
        blo.b   \noscroll

        clr.b   -1(a2,d2.l)             ; Null-terminate the scroll text
        addq    #4,a2                   ; Get past the four bytes we clobbered
        move.l  a2,scroll
\noscroll

        moveq   #0,d0
initout
        movem.l (sp)+,d2-d3/a2-a3
        rts

start
        clr.w   scrollmod               ; Note scroller information

        moveq   #1,d0
        bsr     initfilter

        clr.l   mt_chan1temp+n_realper
        clr.l   mt_chan2temp+n_realper
        clr.l   mt_chan3temp+n_realper
        clr.l   mt_chan4temp+n_realper

        MOVE.B  #6,mt_speed
        CLR.B   mt_counter
        CLR.B   mt_SongPos
        CLR.W   mt_PatternPos

        cq      d0
        cq      d1
        bsr     findnotetab

        st.b    playing
        rts

mt_stop
        clr.b   playing
        rts

fin
        move.l  noteplayer(pc),a0
        jmp     NoteFinish(a0)

usevol  macro
        cmp.w   n_realvol(a6),d0
        beq.b   \usevol\@
        movem.l d1-d2/d4/a0-a1,-(sp)
        move.w  n_channelno(a6),d2
        MOVE.W  D0,d4
        move.w  d0,n_realvol(a6)
        lsl.w   #2,d4
        jsr     NoteVol(a5)
        movem.l (sp)+,d1-d2/d4/a0-a1
\usevol\@:
        endm

useper  macro
        cmp.w   n_realper(a6),d0
        beq.b   \useper\@
        movem.l d1-d3/a0-a1,-(sp)
        move.w  n_channelno(a6),d2
        moveq   #0,d3
        move.w  d0,n_realper(a6)
        MOVE.W  d0,d3
        swap    d3
        jsr     NoteFreq(a5)
        movem.l (sp)+,d1-d3/a0-a1
\useper\@
        endm

* Register conventions:
* d2 = Channel number (not quite yet)
* d5-d7 = Always available
* a5 = NotePlayer
* a6 = chan#temp

mt_music
        movem.l d0-d7/a0-a6,-(SP)            ;

        move.l  noteplayer(pc),a5

        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     mt_chan1temp(PC),A6
        BSR     mt_CheckEfx
        LEA     mt_chan2temp(PC),A6
        BSR     mt_CheckEfx
        LEA     mt_chan3temp(PC),A6
        BSR     mt_CheckEfx
        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
        suba.w  seqadj(pc),a2
        LEA     1084(A0),A0     ;patterndata
        suba.w  blkadj(pc),a0
        MOVEQ   #0,D0
        MOVEQ   #0,D1
        MOVE.B  mt_SongPos(PC),D0
        MOVE.B  0(A2,D0.W),D1
        ASL.L   #8,D1
        ASL.L   #2,D1
        ADD.W   mt_PatternPos(PC),D1

        LEA     mt_chan1temp(PC),A6
        BSR.S   mt_PlayVoice
        LEA     mt_chan2temp(PC),A6
        BSR.S   mt_PlayVoice
        LEA     mt_chan3temp(PC),A6
        BSR.S   mt_PlayVoice
        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  0(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
        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  0(A1,D2.L),n_start(A6)
        MOVE.W  0(A3,D4.L),n_length(A6)
        MOVE.W  0(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

        push    a0/d0-d3/a0        ; BAF - Flash the note on the display
        move.w  (a6),d0
        andi.w  #$fff,d0
        lea     mt_PeriodTable(pc),a0
        moveq   #-1,d1
1$      addq.w  #1,d1
        cmp.w   (a0)+,d0
        blo.b   1$
        move.b  mt_FlashNotes(pc,d1.w),d1
        move.w  n_channelno(a6),d0
        move.b  n_volume(a6),d2
        bsr     intflashnote

        move.l  n_start(a6),a0
        move.w  (a6),d1
        andi.w  #$fff,d1
        move.w  n_length(a6),d2
        add.w   d2,d2
        move.w  6(a3,d4.l),d3
        add.w   d3,d3
        bsr     intflashsample
        pop     a0/d0-d3/a0

        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
        BRA.S   mt_SetRegsVol

mt_FlashNotes   dc.b    0,7,14,21,28,35,42,49,56,64
                dc.b    71,78,85,92,99,106,113,120,128,135
                dc.b    142,149,156,163,170,177,184,192,199,206
                dc.b    213,220,227,234,241,248

mt_NoLoop
        MOVE.L  n_start(A6),D2
        MOVE.L  D2,n_loopstart(A6)
        MOVE.L  D2,n_wavestart(A6)
        MOVE.W  6(A3,D4.L),n_replen(A6) ; Save replen
mt_SetRegsVol
        MOVEQ   #0,D0
        MOVE.B  n_volume(A6),D0
        usevol
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
        tst.b   n_finetune(a6)
        bz      mt_noft
        LEA     mt_PeriodTable(PC),A1
        MOVEQ   #0,D0
        MOVEQ   #36,D2
mt_ftuloop
        CMP.W   0(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  0(A1,D0.W),d1
mt_noft
        move.w  d1,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

        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
        movem.l d1-d4/a0-a1,-(sp)
        move.l  n_start(a6),a0
        moveq   #0,d0
        move.w  n_length(a6),d0
        add.l   d0,d0
        move.l  n_loopstart(a6),a1
        moveq   #0,d1
        move.w  n_replen(a6),d1
        cmp.w   #1,d1
        bne.b   \notone
        moveq   #0,d1
\notone
        add.l   d1,d1
        move.w  n_channelno(a6),d2
        moveq   #0,d3
        move.w  n_period(a6),d3
        move.w  d3,n_realper(a6)
        swap    d3
        moveq   #0,d4
        move.b  n_volume(a6),d4
        move.w  d4,n_realvol(a6)
        lsl.w   #2,d4
        jsr     NoteStart(a5)
        movem.l (sp)+,d1-d4/a0-a1
        BRA     mt_CheckMoreEfx

mt_SetDMA

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_NoNewBlock
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
        move.b  mt_SongPos(pc),d1       ; Fixes and opts
        addq.B  #1,d1
        and.B   #$7F,d1
        move.L  mt_SongDataPtr(PC),A0
        suba.w  seqadj(pc),a0
        move.b  $3b6(a0),d2
        cmp.b   d2,d1
        blo.s   1$

        bsr     intrepeat               ; Signal when repeating

        move.b  $3b7(a0),d1
        cmp.b   d2,d1                   ; < Fix - range check for song repeat
        blo.s   1$
        moveq   #0,d1
1$      move.b  d1,mt_SongPos

        moveq   #0,d0                   ; Update MultiPlayer's position display
        move.b  d1,d0
        moveq   #0,d1
        move.b  d2,d1
        jsr     intsongpos

        bsr.b   findnotetab

mt_NoNewBlock
        move.w  mt_PatternPos(pc),d0    ; Update the scrolling note display
        lsr.w   #4,d0
        moveq   #64,d1
        jsr     intflashscroll

mt_NoNewPosYet
        TST.B   mt_PosJumpFlag
        BNE     mt_NextPosition

mt_exit movem.l (sp)+,d0-d7/a0-a6
        RTS


findnotetab
        MOVE.L  mt_SongDataPtr(PC),A0   ; Find the new note table
        LEA     952(A0),A2
        suba.w  seqadj(pc),a2
        LEA     1084(A0),A0
        suba.w  blkadj(pc),a0
        MOVE.B  0(A2,D0.W),D1
        ASL.L   #8,D1
        ASL.L   #2,D1
        add.l   d1,a0
        move.l  a0,notetab
        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     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  d0,-(sp)
        move.w  n_period(a6),d0
        useper
        move.w  (sp)+,d0
        CMP.B   #7,D0
        BEQ     mt_Tremolo
        CMP.B   #$A,D0
        BEQ     mt_VolumeSlide
mt_Return2
        RTS

mt_PerNop
        move.w  n_period(a6),d0
        useper
        RTS


*** mt_Arpeggio - Process arpeggio commands (off-cycles)
mt_Arpeggio
        MOVEQ   #0,D7
        MOVE.B  mt_counter(PC),D7
        divu.w  #3,D7
        swap    d7
        subq.w  #1,d7
        blo.s   \mt_Arpeggio2
        bhi.S   \mt_Arpeggio1
        MOVE.B  n_cmdlo(A6),D7
        LSR.B   #4,D7
        BRA.S   \mt_Arpeggio3

\mt_Arpeggio1
        MOVE.B  n_cmdlo(A6),D7
        AND.w   #$f,D7
        BRA.S   \mt_Arpeggio3

\mt_Arpeggio2
        MOVE.W  n_period(A6),D0
        BRA.S   \mt_Arpeggio4

\mt_Arpeggio3
        add.w   d7,d7
        MOVEQ   #0,D1
        MOVE.B  n_finetune(A6),D1
        MULU    #36*2,D1
        LEA     mt_PeriodTable(PC),A0
        ADD.w   D1,A0
        MOVEQ   #0,D1
        MOVE.W  n_period(A6),D1
        MOVEQ   #36,D6
\mt_arploop
        CMP.W   (A0)+,D1
        BHS.S   \mt_Arpeggio4a
        DBRA    D6,\mt_arploop
        RTS

\mt_Arpeggio4a
        MOVE.W  -2(A0,D7.W),D0
\mt_Arpeggio4
        useper
        RTS



mt_FinePortaUp
        TST.B   mt_counter
        BNE     mt_Return2
        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
        useper
        RTS



mt_FinePortaDown
        TST.B   mt_counter
        BNE     mt_Return2
        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
        useper
        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    #36*2,D0
        LEA     mt_PeriodTable(PC),A0
        ADD.L   D0,A0
        MOVEQ   #0,D0
mt_StpLoop
        CMP.W   0(A0,D0.W),D2
        BHS.S   mt_StpFound
        ADDQ.W  #2,D0
        CMP.W   #36*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  0(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_Return2
        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_Return2
        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   0(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  0(A0,D0.W),D2
mt_GlissSkip
        move.w  d2,d0
        useper
        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  0(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
        useper
        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     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  0(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
        usevol
        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 ($A), mt_VolumeFineUp ($EA), mt_VolumeFineDown ($EB)
mt_VolumeSlide
        MOVEQ   #0,D0
        MOVE.B  n_cmdlo(A6),D0
        LSR.B   #4,D0
        BEQ.S   vol_VolSlideDown

vol_VolSlideUp
        ADD.B   n_volume(A6),d0
        CMP.B   #$40,d0
        bls.S   \mt_vsuskip
        moveq   #$40,d0
\mt_vsuskip
        MOVE.B  d0,n_volume(A6)
        bra     vol_set

mt_VolumeFineUp
        TST.B   mt_counter
        BNE     mt_Return2
        MOVE.B  n_cmdlo(A6),D0
        and.w   #$F,D0
        BRA     vol_VolSlideUp

vol_VolSlideDown
        MOVE.B  n_cmdlo(A6),D0
        AND.w   #$0F,D0
vol_VolSlideDown2
        SUB.B   D0,n_volume(A6)
        bhs.S   \mt_vsdskip
        CLR.B   n_volume(A6)
\mt_vsdskip

        MOVE.B  n_volume(A6),d0
vol_set
        usevol
        RTS

mt_VolumeFineDown
        TST.B   mt_counter
        BNE     mt_Return2
        MOVE.B  n_cmdlo(A6),D0
        AND.w   #$0F,D0
        BRA     vol_VolSlideDown2



mt_PositionJump
        MOVE.B  n_cmdlo(A6),D0

        cmp.b   mt_SongPos(pc),d0       ; Check for repeat
        bhi.s   1$
        jsr     intrepeat
1$
        SUBQ.B  #1,D0
        MOVE.B  D0,mt_SongPos
mt_pj2  CLR.B   mt_PBreakPos
        ST      mt_PosJumpFlag
        RTS


*** mt_VolumeChange - Effect $C, on-cycles
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)
        usevol
        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     \out
        CMP.B   #$20,D0
        blo.b   \normal
        btst.b  #MNB_PTTEMPO,modflags
        bnz     SetTempo
\normal
        CLR.B   mt_counter
        MOVE.B  D0,mt_speed
\out
        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     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     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
initfilter
        move.b  d0,modfilter
setfilter
        tst.b   filter
        ble.b   \modcontrol
        moveq   #2,d0
        sub.b   filter,d0
\modcontrol
        add.b   d0,d0
        and.b   #2,d0
        AND.B   #$FD,$BFE001
        OR.B    D0,$BFE001
        RTS

ptfilter
        tst.b   playing
        bz      mt_Return2
        move.b  modfilter(pc),d0
        bra.b   setfilter


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_Return2
        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_Return2
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
        movem.l d2-d4/a0-a1,-(sp)
        move.l  n_start(a6),a0
        moveq   #0,d0
        move.w  n_length(a6),d0
        add.l   d0,d0
        move.l  n_loopstart(a6),a1
        moveq   #0,d1
        move.w  n_replen(a6),d1
        cmp.w   #1,d1
        bne.b   \notone
        moveq   #0,d1
\notone
        add.l   d1,d1
        move.w  n_channelno(a6),d2
        moveq   #0,d3
        move.w  n_period(a6),d3
        move.w  d3,n_realper(a6)
        swap    d3
        moveq   #0,d4
        move.b  n_volume(a6),d4
        move.w  d4,n_realvol(a6)
        lsl.w   #2,d4
        jsr     NoteStart(a5)
        movem.l (sp)+,d2-d4/a0-a1
mt_rtnend
        MOVE.L  (SP)+,D1
        RTS


mt_NoteCut
        MOVEQ   #0,D0
        MOVE.B  n_cmdlo(A6),D0
        AND.B   #$0F,D0
        CMP.B   mt_counter(PC),D0
        BNE     mt_Return2
        CLR.B   n_volume(A6)
        moveq   #0,d0
        usevol
        RTS

mt_NoteDelay
        MOVEQ   #0,D0
        MOVE.B  n_cmdlo(A6),D0
        AND.B   #$0F,D0
        CMP.B   mt_counter,D0
        BNE     mt_Return2
        MOVE.W  (A6),D0
        BEQ     mt_Return2
        MOVE.L  D1,-(SP)
        BRA     mt_DoRetrig

mt_PatternDelay
        TST.B   mt_counter
        BNE     mt_Return2
        MOVEQ   #0,D0
        MOVE.B  n_cmdlo(A6),D0
        AND.B   #$0F,D0
        TST.B   mt_PattDelTime2
        BNE     mt_Return2
        ADDQ.B  #1,D0
        MOVE.B  D0,mt_PattDelTime
        RTS

mt_FunkIt
        TST.B   mt_counter
        BNE     mt_Return2
        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_Return2
mt_UpdateFunk
        MOVEM.L D1/A0,-(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  0(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)+,D1/A0
        RTS


SetTempo
        push    a0/d0/d1
        move.w  d0,d1
        move.l  4,a0
        move.l  #1789773,d0
        cmp.b   #50,PowerSupplyFrequency(a0)
        bne.s   2$
        move.l  #1773447,d0
2$      divu.w  d1,d0
        bsr     changetintcia
        pop     a0/d0/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,0
mt_chan2temp    dc.l    0,0,0,0,0,$00020000,0,0,0,0,1,0
mt_chan3temp    dc.l    0,0,0,0,0,$00040000,0,0,0,0,2,0
mt_chan4temp    dc.l    0,0,0,0,0,$00080000,0,0,0,0,3,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

scroll          dc.l    0

noteplayer      dc.l    0

mt_PatternPos   dc.w 0
mt_DMACONtemp   dc.w 0

seqadj          dc.w    0               ; < Fix - for old modules
blkadj          dc.w    0

mt_speed        dc.b 0
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,0

modfilter       dc.b    0

playing         dc.b    0

name            dc.b    "Sound/Noise/ProTracker",0

        end