        section "play",CODE
        include "exec/types.i"
        include "libraries/dos.i"
        include "streplay_lib.i"
        xdef    mt_start
        xdef    mt_brems

call    MACRO
        xref    _LVO\1
        jsr     _LVO\1(a6)
        ENDM

        even
mt_start:
        movem.l d2-d7/a2-a6,-(sp)
        bsr     mt_init
        move.l  4,a6
        lea     intnode(pc),a1
        moveq   #5,d0
        call    AddIntServer
        movem.l (sp)+,d2-d7/a2-a6
        rts

mt_brems:
        movem.l d2-d7/a2-a6,-(sp)
        lea     intnode(pc),a1
        moveq   #5,d0
        move.l  4,a6
        call    RemIntServer
        bsr     mt_end
        movem.l (sp)+,d2-d7/a2-a6
        rts


intnode:
        dc.l    0,0
        dc.b    2,0
        dc.l    intname,0,mt_call
intname:
        dc.b    "STReplay_Lib Interrupt",0
        even

mt_init:
        moveq   #6,d0
        bsr inits
        move.l  strb_Module(a6),a0
        move.l  a0,mt_data
        add.l   #$03b8,a0
        moveq   #$7f,d0
        moveq   #0,d1
mt_init1:
        move.l  d1,d2
        subq.w  #1,d0
mt_init2:
        move.b  (a0)+,d1
        cmp.b   d2,d1
        bgt     mt_init1
        dbf     d0,mt_init2
        addq.b  #1,d2

mt_init3:
        move.l  mt_data(pc),a0
        lea     mt_sample1(pc),a1
        asl.l   #8,d2
        asl.l   #2,d2
        add.l   #$438,d2
        add.l   a0,d2
        moveq   #$1e,d0
mt_init4:
        move.l  d2,(a1)+
        moveq   #0,d1
        move.w  42(a0),d1
        asl.l   #1,d1
        add.l   d1,d2
        add.l   #$1e,a0
        dbf     d0,mt_init4

        lea     mt_sample1(PC),a0
        moveq   #0,d0
mt_clear:
        move.l  0(a0,d0.w),a1
        clr.l   (a1)
        addq.w  #4,d0
        cmp.w   #$7c,d0
        bne     mt_clear

        clr.w   $dff0a8
        clr.w   $dff0b8
        clr.w   $dff0c8
        clr.w   $dff0d8
        clr.l   mt_partnrplay
        clr.l   mt_partnote
        clr.l   mt_partpoint

        move.l  mt_data(pc),a0
        move.b  $3b6(a0),mt_maxpart+1
        rts

; call 'mt_end' to switch the sound off

mt_end: clr.w   $dff0a8
        clr.w   $dff0b8
        clr.w   $dff0c8
        clr.w   $dff0d8
        move.w  #$f,$dff096
        rts

; the playroutine - call this every frame

mt_call:
        movem.l d2-d7/a2-a6,-(sp)
        bsr.s   mt_music
        movem.l (sp)+,d2-d7/a2-a6
        rts

mt_music:
        addq.w  #1,mt_counter
mt_cool: cmp.w  #6,mt_counter
        bne     mt_notsix
        clr.w   mt_counter
        bra     mt_rout2

mt_notsix:
        lea     mt_aud1temp(PC),a6
        tst.b   3(a6)
        beq     mt_arp1
        lea     $dff0a0,a5
        bsr     mt_arprout
mt_arp1: lea    mt_aud2temp(PC),a6
        tst.b   3(a6)
        beq     mt_arp2
        lea     $dff0b0,a5
        bsr     mt_arprout
mt_arp2: lea    mt_aud3temp(PC),a6
        tst.b   3(a6)
        beq     mt_arp3
        lea     $dff0c0,a5
        bsr     mt_arprout
mt_arp3: lea    mt_aud4temp(PC),a6
        tst.b   3(a6)
        beq     mt_arp4
        lea     $dff0d0,a5
        bra     mt_arprout
mt_arp4: rts

mt_arprout:
        move.b  2(a6),d0
        and.b   #$0f,d0
        tst.b   d0
        beq     mt_arpegrt
        cmp.b   #$01,d0
        beq     mt_portup
        cmp.b   #$02,d0
        beq     mt_portdwn
        cmp.b   #$0a,d0
        beq     mt_volslide
        rts

mt_portup:
        moveq   #0,d0
        move.b  3(a6),d0
        sub.w   d0,22(a6)
        cmp.w   #$71,22(a6)
        bpl     mt_ok1
        move.w  #$71,22(a6)
mt_ok1: move.w  22(a6),6(a5)
        rts

mt_portdwn:
        moveq   #0,d0
        move.b  3(a6),d0
        add.w   d0,22(a6)
        cmp.w   #$538,22(a6)
        bmi     mt_ok2
        move.w  #$538,22(a6)
mt_ok2: move.w  22(a6),6(a5)
        rts

mt_volslide:
        moveq   #0,d0
        move.b  3(a6),d0
        lsr.b   #4,d0
        tst.b   d0
        beq     mt_voldwn
        add.w   d0,18(a6)
        cmp.w   #64,18(a6)
        bmi     mt_ok3
        move.w  #64,18(a6)
mt_ok3: move.w  18(a6),8(a5)
        rts
mt_voldwn:
        moveq   #0,d0
        move.b  3(a6),d0
        and.b   #$0f,d0
        sub.w   d0,18(a6)
        bpl     mt_ok4
        clr.w   18(a6)
mt_ok4: move.w  18(a6),8(a5)
        rts

mt_arpegrt:
        move.w  mt_counter(PC),d0
        cmp.w   #1,d0
        beq     mt_loop2
        cmp.w   #2,d0
        beq     mt_loop3
        cmp.w   #3,d0
        beq     mt_loop4
        cmp.w   #4,d0
        beq     mt_loop2
        cmp.w   #5,d0
        beq     mt_loop3
        rts

mt_loop2:
        moveq   #0,d0
        move.b  3(a6),d0
        lsr.b   #4,d0
        bra     mt_cont
mt_loop3:
        moveq   #$00,d0
        move.b  3(a6),d0
        and.b   #$0f,d0
        bra     mt_cont
mt_loop4:
        move.w  16(a6),d2
        bra     mt_endpart
mt_cont:
        add.w   d0,d0
        moveq   #0,d1
        move.w  16(a6),d1
        and.w   #$fff,d1
        lea     mt_arpeggio(PC),a0
mt_loop5:
        move.w  0(A0,d0),d2
        cmp.w   (a0),d1
        beq     mt_endpart
        addq.l  #2,a0
        bra     mt_loop5
mt_endpart:
        move.w  d2,6(a5)
        rts

mt_rout2:
        move.l  mt_data(pc),a0
        move.l  a0,a3
        add.l   #$0c,a3
        move.l  a0,a2
        add.l   #$3b8,a2
        add.l   #$43c,a0
        move.l  mt_partnrplay(PC),d0
        moveq   #0,d1
        move.b  0(A2,d0),d1
        asl.l   #8,d1
        asl.l   #2,d1
        add.l   mt_partnote(PC),d1
        move.l  d1,mt_partpoint
        clr.w   mt_dmacon

        lea     $dff0a0,a5
        lea     mt_aud1temp(PC),a6
        bsr     mt_playit
        lea     $dff0b0,a5
        lea     mt_aud2temp(PC),a6
        bsr     mt_playit
        lea     $dff0c0,a5
        lea     mt_aud3temp(PC),a6
        bsr     mt_playit
        lea     $dff0d0,a5
        lea     mt_aud4temp(PC),a6
        bsr     mt_playit
        move.w  #$01f4,d0
mt_rls: dbf     d0,mt_rls

        move.w  #$8000,d0
        or.w    mt_dmacon,d0
        move.w  d0,$dff096

        lea     mt_aud4temp(PC),a6
        cmp.w   #1,14(a6)
        bne     mt_voice3
        move.l  10(a6),$dff0d0
        move.w  #1,$dff0d4
mt_voice3:
        lea     mt_aud3temp(PC),a6
        cmp.w   #1,14(a6)
        bne     mt_voice2
        move.l  10(a6),$dff0c0
        move.w  #1,$dff0c4
mt_voice2:
        lea     mt_aud2temp(PC),a6
        cmp.w   #1,14(a6)
        bne     mt_voice1
        move.l  10(a6),$dff0b0
        move.w  #1,$dff0b4
mt_voice1:
        lea     mt_aud1temp(PC),a6
        cmp.w   #1,14(a6)
        bne     mt_voice0
        move.l  10(a6),$dff0a0
        move.w  #1,$dff0a4
mt_voice0:
        move.l  mt_partnote(PC),d0
        add.l   #$10,d0
        move.l  d0,mt_partnote
        cmp.l   #$400,d0
        bne     mt_stop
mt_higher:
        clr.l   mt_partnote
        addq.l  #1,mt_partnrplay
        moveq   #0,d0
        move.w  mt_maxpart(PC),d0
        move.l  mt_partnrplay(PC),d1
        cmp.l   d0,d1
        bne     mt_stop
        clr.l   mt_partnrplay
;       st      Pflag
mt_stop: tst.w  mt_status
        beq     mt_stop2
        clr.w   mt_status
        bra     mt_higher
mt_stop2:
        rts

mt_playit:
        move.l  0(A0,d1.l),(a6)
        addq.l  #4,d1
        moveq   #0,d2
        move.b  2(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_nosamplechange

        moveq   #0,d3
        lea     mt_samples(PC),a1
        move.l  d2,d4
        asl.l   #2,d2
        mulu    #$1e,d4
        move.l  0(A1,d2),4(a6)
        move.w  0(A3,d4.l),8(a6)
        move.w  2(A3,d4.l),18(a6)
        move.w  4(A3,d4.l),d3
        tst.w   d3
        beq     mt_displace
        move.l  4(a6),d2
        add.l   d3,d2
        move.l  d2,4(a6)
        move.l  d2,10(a6)
        move.w  6(a3,d4.l),8(a6)
        move.w  6(a3,d4.l),14(a6)
        move.w  18(a6),8(a5)
        bra     mt_nosamplechange

mt_displace:
        move.l  4(a6),d2
        add.l   d3,d2
        move.l  d2,10(a6)
        move.w  6(a3,d4.l),14(a6)
        move.w  18(a6),8(a5)
mt_nosamplechange:
        move.w  (a6),d0
        and.w   #$fff,d0
        tst.w   d0
        beq     mt_retrout
        move.w  (a6),16(a6)
        move.w  20(a6),$dff096
        move.l  4(a6),(a5)
        move.w  8(a6),4(a5)
        move.w  (a6),d0
        and.w   #$fff,d0
        move.w  d0,6(a5)
        move.w  20(a6),d0
        or.w    d0,mt_dmacon

mt_retrout:
        tst.w   (a6)
        beq     mt_nonewper
        move.w  (a6),22(a6)

mt_nonewper:
        move.b  2(a6),d0
        and.b   #$0f,d0
        cmp.b   #$0b,d0
        beq     mt_posjmp
        cmp.b   #$0c,d0
        beq     mt_setvol
        cmp.b   #$0d,d0
        beq     mt_break
        cmp.b   #$0e,d0
        beq     mt_setfil
        cmp.b   #$0f,d0
        beq     mt_setspeed
        rts

mt_posjmp:
        not.w   mt_status
        moveq   #0,d0
        move.b  3(a6),d0
        subq.b  #1,d0
        move.l  d0,mt_partnrplay
        rts

mt_setvol:
        move.b  3(a6),8(a5)
        rts

mt_break:
        not.w   mt_status
        rts

mt_setfil:
        moveq   #0,d0
        move.b  3(a6),d0
        and.b   #1,d0
        rol.b   #1,d0
        and.b   #$fd,$bfe001
        or.b    d0,$bfe001
        rts

mt_setspeed:
        move.b  3(a6),d0
        and.b   #$0f,d0
        beq     mt_back
inits:  clr.w   mt_counter
        move.b  d0,mt_cool+3
mt_back: rts

mt_aud1temp:
        ds.w    10
        dc.w    1
        ds.w    2
mt_aud2temp:
        ds.w    10
        dc.w    2
        ds.w    2
mt_aud3temp:
        ds.w    10
        dc.w    4
        ds.w    2
mt_aud4temp:
        ds.w    10
        dc.w    8
        ds.w    2

mt_partnote:    dc.l    0
mt_partnrplay:  dc.l    0
mt_counter:     dc.w    0
mt_partpoint:   dc.l    0
mt_samples:     dc.l    0
mt_sample1:     ds.l    31
mt_maxpart:     dc.w    0
mt_dmacon:      dc.w    0
mt_status:      dc.w    0

mt_arpeggio:
        dc.w $0358,$0328,$02fa,$02d0,$02a6,$0280,$025c
        dc.w $023a,$021a,$01fc,$01e0,$01c5,$01ac,$0194,$017d
        dc.w $0168,$0153,$0140,$012e,$011d,$010d,$00fe,$00f0
        dc.w $00e2,$00d6,$00ca,$00be,$00b4,$00aa,$00a0,$0097
        dc.w $008f,$0087,$007f,$0078,$0071,$0000,$0000,$0000
mt_data:        dc.l    0

        END
