*******************************************************************************
**   Soundtracker V2.5 PlayRoutine                    |Call The Castle       **
**   Based on the playroutine from TJC                |214-618-3047          **
**   Improved and optimized from the DOC V2.3 Routine |----------------------**
**   By The INTRUDER/SOLO                                     January 7,1990 **
*******************************************************************************
**                                                                           **
** This program has three entry points,                                      **
**                                                                           **
**             mt_init :  Initialize The Music Structure                     **
**            mt_music :  main player routine ( Must be played each VBlank ) **
**              mt_end :  after you finish the music, turn voices off.       **
**                                                                           **
** Hope you enjoy this as I enjoyed studying/ripping/modifying DOC's to work **
** with all the existant SoundTracker modules.                               **
**                                                                           **
** (C)1990 Karsten Obarski, Neumotron and The Intruder of Puerto Rico.       **
** Use it in your programs, but don't charge for them.. Public Domestos      **
*******************************************************************************
** Assembled with ArgAsm, The Best Assembler... Buy this Assembler, don't    **
** Pirate it, Help support good coderz... BTW, This code assembles in 0.00   **
** seconds... Preety Nippy!                                                  **
*******************************************************************************
** Greetingz go to: Instinct, Mandrake and Zodact/Razor and the Menace       **
*******************************************************************************
** At this moment I'm rewrinting most of the player to reentrant and be OS   **
** Friendly.. so it will use "audio.device" and "timer.device"               **
**                                                                           **
** The Intruder/PRH                                                          **
*******************************************************************************

               section  aspo,code_c

player         movem.l  d0-d7/a0-a6,-(sp)
               move.l   $4,a6
               suba.l   a1,a1
               jsr      -$126(a6)
               move.l   d0,a0
               move.l   a0,mtask
               move.b   9(a0),mtaskpri
               move.b   #-128,9(a0)

               bsr.s    mt_init
               move.l   $6c.w,inter_tmp
               lea      vblank_int,a0
               move.l   a0,$6c.w
.loop          btst     #6,$bfe001
               bne.s    .loop
               move.l   inter_tmp,$6c.w
               bsr      mt_end
               move.l   mtask(pc),a6
               move.b   mtaskpri(pc),9(a6)
               movem.l  (sp)+,d0-d7/a0-a6
               rts
mtask          dl       0
mtaskpri       db       0
               even

vblank_int     movem.l  d0-d7/a0-a6,-(sp)
               move.w   $dff01e,d0
               btst     #5,d0
               beq.s    .abort
               bsr.w    mt_music
.abort         movem.l  (sp)+,d0-d7/a0-a6
               jmp      appart
*****************************************************************************

*------------------    MT_INIT
mt_init
               lea     mt_data(pc),a0
               cmp.l   #'M.K.',$438(a0)
               bne     not_m_k

               lea     new_offsets(pc),a2
               move.l  a2,mt_offset
               bra     mt_brkpnt

not_m_k        lea     old_offsets(pc),a2
               move.l  a2,mt_offset
mt_brkpnt      add.l   (a2),a0
               moveq   #$7F,d0
               moveq   #$0,d1
mt_init_add    move.l  d1,d2
               subq.w  #$1,d0
.loop          move.b  (a0)+,d1
               cmp.b   d2,d1
               bgt.s   mt_init_add

               dbra    d0,.loop

mt_init3       addq.b  #$1,d2
               lea     mt_data(pc),a0
               lea     mt_sample1(pc),a1
               asl.l   #$8,d2
               asl.l   #$2,d2
               add.l   $4(a2),d2
               add.l   a0,d2
               move.l  $8(a2),d0
.loop          move.l  d2,(a1)+
               moveq   #$0,d1
               move.w  $2A(a0),d1
               asl.l   #$1,d1
               add.l   d1,d2
               add.l   #$1E,a0
               dbra    d0,.loop

               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.s   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
               lea     mt_data(pc),a1
               add.l   $C(a2),a1
               move.b  (a1),mt_dmnons
               rts
*------------------ MT_END
mt_end         clr.w   $DFF0A8
               clr.w   $DFF0B8
               clr.w   $DFF0C8
               clr.w   $DFF0D8
               move.w  #$F,$DFF096
               rts
*------------------ MT_MUSIC
mt_music       addq.w  #$1,mt_counter
               cmp.w   #$6,mt_counter
mt_cool        equ     *-5
               bne.s   mt_notsix

               clr.w   mt_counter
               bra     mt_rout2

mt_notsix      lea     mt_aud1temp(pc),a6
               tst.b   $3(a6)
               beq.s   mt_arp1

               lea     $DFF0A0,a5
               bsr.s   mt_arpout

mt_arp1        lea     mt_aud2temp(pc),a6
               tst.b   $3(a6)
               beq.s   mt_arp2

               lea     $DFF0B0,a5
               bsr.s   mt_arpout

mt_arp2        lea     mt_aud3temp(pc),a6
               tst.b   $3(a6)
               beq.s   mt_arp3

               lea     $DFF0C0,a5
               bsr.s   mt_arpout

mt_arp3        lea     mt_aud4temp(pc),a6
               tst.b   $3(a6)
               beq.s   mt_arp4

               lea     $DFF0D0,a5
               bra.s   mt_arpout

mt_arp4 rts

mt_arpout      move.b  $2(a6),d0
               and.b   #$F,d0
               tst.b   d0
               beq     mt_arpegrt

               cmp.b   #$1,d0
               beq.s   mt_portup

               cmp.b   #$2,d0
               beq.s   mt_portdwn

               cmp.b   #$A,d0
               beq.s   mt_volslide

               rts

mt_portup      moveq   #$0,d0
               move.b  $3(a6),d0
               sub.w   d0,$16(a6)
               cmp.w   #$71,$16(a6)
               bpl.s   mt_ok1

               move.w  #$71,$16(a6)
mt_ok1         move.w  $16(a6),$6(a5)
               rts

mt_portdwn     moveq   #$0,d0
               move.b  $3(a6),d0
               add.w   d0,$16(a6)
               cmp.w   #$538,$16(a6)
               bmi.s   mt_ok2

               move.w  #$538,$16(a6)
mt_ok2         move.w  $16(a6),$6(a5)
               rts

mt_volslide    moveq   #$0,d0
               move.b  $3(a6),d0
               lsr.b   #$4,d0
               tst.b   d0
               beq.s   mt_voldwn

               add.w   d0,$12(a6)
               cmp.w   #$40,$12(a6)
               bmi.s   mt_ok3

               move.w  #$40,$12(a6)
mt_ok3         move.w  $12(a6),$8(a5)
               rts

mt_voldwn      moveq   #$0,d0
               move.b  $3(a6),d0
               and.b   #$F,d0
               sub.w   d0,$12(a6)
               bpl.s   mt_ok4

               clr.w   $12(a6)
mt_ok4         move.w  $12(a6),$8(a5)
               rts

mt_arpegrt     move.w  mt_counter(pc),d0
               cmp.w   #$1,d0
               beq.s   mt_loop2

               cmp.w   #$2,d0
               beq.s   mt_loop3

               cmp.w   #$3,d0
               beq.s   mt_loop4

               cmp.w   #$4,d0
               beq.s   mt_loop2

               cmp.w   #$5,d0
               beq.s   mt_loop3

               rts

mt_loop2       moveq   #$0,d0
               move.b  $3(a6),d0
               lsr.b   #$4,d0
               bra.s   mt_cont

mt_loop3       moveq   #$0,d0
               move.b  $3(a6),d0
               and.b   #$F,d0
               bra.s   mt_cont

mt_loop4       move.w  $10(a6),d2
               bra.s   mt_endpart

mt_cont        add.w   d0,d0
               moveq   #$0,d1
               move.w  $10(a6),d1
               lea     mt_arpeggio(pc),a0
mt_loop5       move.w  $0(a0,d0.l),d2
               cmp.w   (a0),d1
               beq.s   mt_endpart

               addq.l  #$2,a0
               bra.s   mt_loop5

mt_endpart     move.w  d2,$6(a5)
               rts

mt_rout2       lea     mt_data(pc),a0
               move.l  a0,a3
               add.l   #$C,a3
               move.l  a0,a2
               move.l  mt_offset,a4
               add.l   (a4),a2
               add.l   $10(a4),a0
               move.l  mt_partnrplay(pc),d0
               moveq   #$0,d1
               move.b  $0(a2,d0.l),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
.loop          dbf     d0,.loop

               move.w  #$8000,d0
               or.w    mt_dmacon,d0
               move.w  d0,$DFF096
               lea     mt_aud4temp(pc),a6
               cmp.w   #$1,$E(a6)
               bne.s   mt_voice3

               move.l  $A(a6),$DFF0D0
               move.w  #$1,$DFF0D4
mt_voice3      lea     mt_aud3temp(pc),a6
               cmp.w   #$1,$E(a6)
               bne.s   mt_voice2

               move.l  $A(a6),$DFF0C0
               move.w  #$1,$DFF0C4
mt_voice2      lea     mt_aud2temp(pc),a6
               cmp.w   #$1,$E(a6)
               bne.s   mt_voice1

               move.l  $A(a6),$DFF0B0
               move.w  #$1,$DFF0B4
mt_voice1      lea     mt_aud1temp(pc),a6
               cmp.w   #$1,$E(a6)
               bne.s   mt_voice0

               move.l  $A(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.s   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.s   mt_stop

               clr.l   mt_partnrplay
mt_stop        tst.w   mt_status
               beq.s   mt_stop2

               clr.w   mt_status
               bra.s   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.s   mt_nochange

               moveq   #$0,d3
               lea     mt_samples(pc),a1
               move.l  d2,d4
               lsl.l   #$2,d2
               mulu    #$1E,d4
               move.l  $0(a1,d2.l),$4(a6)
               move.w  $0(a3,d4.l),$8(a6)
               move.w  $2(a3,d4.l),$12(a6)
               move.w  $4(a3,d4.l),d3
               tst.w   d3
               beq.s   mt_displace

               move.l  $4(a6),d2
               add.l   d3,d2
               move.l  d2,$4(a6)
               move.l  d2,$A(a6)
               move.w  $6(a3,d4.l),$8(a6)
               move.w  $6(a3,d4.l),$E(a6)
               move.w  $12(a6),$8(a5)
               bra.s   mt_nochange

mt_displace    move.l  $4(a6),d2
               add.l   d3,d2
               move.l  d2,$A(a6)
               move.w  $6(a3,d4.l),$E(a6)
               move.w  $12(a6),$8(a5)
mt_nochange    move.w  (a6),d0
               and.w   #$FFF,d0
               tst.w   d0
               beq.s   mt_retrout

               move.w  (a6),$10(a6)
               move.w  $14(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  $14(a6),d0
               or.w    d0,mt_dmacon
mt_retrout     tst.w   (a6)
               beq.s   mt_nonewper

               move.w  (a6),$16(a6)
mt_nonewper    move.b  $2(a6),d0
               and.b   #$F,d0
               cmp.b   #$B,d0
               beq.s   mt_posjump

               cmp.b   #$C,d0
               beq.s   mt_setvolume

               cmp.b   #$D,d0
               beq.s   mt_break

               cmp.b   #$E,d0
               beq.s   mt_setfil

               cmp.b   #$F,d0
               beq.s   mt_setspeed

               rts

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

mt_setvolume   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   #$F,d0
               beq.s   mt_back

               clr.w   mt_counter
               move.b  d0,mt_cool
mt_back        rts

audio          macro
               ds.w    10
               dw      \1
               ds.w    2
               endm

mt_aud1temp    audio   1
mt_aud2temp    audio   2
mt_aud3temp    audio   4
mt_aud4temp    audio   8

mt_partnote    dl      0
mt_partnrplay  dl      0
mt_counter     dw      0
mt_partpoint   dl      0
mt_samples     dl      0
mt_sample1     ds.l    31
mt_maxpart     dw      0
mt_dmnons      equ     *-1
mt_dmacon      dw      0
mt_status      dw      0
mt_offset      dl      0

old_offsets    dl      $01D8,$0258,$000e,$01d6,$0258
new_offsets    dl      $03B8,$0438,$001e,$03b6,$043c

mt_arpeggio    dw      $0358,$0328,$02fa,$02d0,$02a6,$0280,$025c
               dw      $023a,$021a,$01fc,$01e0,$01c5,$01ac,$0194,$017d
               dw      $0168,$0153,$0140,$012e,$011d,$010d,$00fe,$00f0
               dw      $00e2,$00d6,$00ca,$00be,$00b4,$00aa,$00a0,$0097
               dw      $008f,$0087,$007f,$0078,$0071,$0000,$0000,$0000
               dw      $0000,$0001
mt_data        incbin   "df1:mod.delta"
inter_tmp      equ      *+2
appart         jmp      $fc0000

