; (C) DIRE CRACKS Inc.
; All rights reserved.
; NON-SYSTEM-COOP-VERSION
; FOR ASSEMBLY PROGRAMMERS, WHO TAKE OVER THE MACHINE TOTALLY
;

; ROUTINES
 xdef _soundon,_soundoff,_generalsndinit,_decrunchinstrs
 xdef _generalsndreset,_setvolume,_setspeed

; FLAGS
 xdef _channelsfinished,_fadeflag,_fadefinished

; THE INTERRUPT PROGRAM
 xdef _generalplay 

; *** SOUND ROUTINES START

INSTNUM equ 26

_soundon:
 movem.l a0/a5-a6/d0,-(a7)
 bsr hardwareinit
 lea.l mystructure(PC),a5
 moveq.l #1,d0
 move.w d0,curspeedfact1-ms(a5)
 move.w d0,curspeedfact2-ms(a5)
 move.w speed-ms(a5),d0
 mulu #23,d0
 move.w d0,playspeed-ms(a5)
 bsr settimer
 move.w #$e000,$09a(a6)
 sf soundenable-ms(a5)
 movem.l (a7)+,a0/a5-a6/d0
 rts

_soundoff:
 movem.l a5-a6/d0,-(a7)
 lea.l mystructure(PC),a5
 st soundenable-ms(a5)
 bsr hardwareinit
 movem.l (a7)+,a5-a6/d0
 rts

_generalsndreset:    ; d0=oneshot
 movem.l d0-d7/a0-a6,-(a7)
 lea.l mystructure(PC),a5
 move.l myinstrsdata-ms(a5),a1
 move.l mymacrosdata-ms(a5),a2
internsndreset:
 sf internfinished-ms(a5)
 sf _channelsfinished-ms(a5)
 sf _fadeflag-ms(a5)
 sf _fadefinished-ms(a5)
 sf channelshandle-ms(a5)
 sf called-ms(a5)
 sf doloudness-ms(a5)
 sf dofadein-ms(a5)
 sf dofadeout-ms(a5)
 move.b d0,oneshot-ms(a5)
 bsr.s setbacklaststuff
 move.w (a2)+,d0
 cmpi.w #'SE',d0
 bne.s nosongname
   adda.w #20,a2
   move.w (a2)+,d0
nosongname:
 move.w d0,pattlen-ms(a5)
 move.w (a2)+,d0
 move.w d0,speed-ms(a5)
 move.w d0,calcspeed-ms(a5)
 mulu #23,d0
 move.w d0,playspeed-ms(a5)
 clr.w whattodo-ms(a5)
 bsr ptrsinit
 bsr hardwareinit
 movem.l (a7)+,d0-d7/a0-a6
 rts
setbacklaststuff:
 movem.l d0/a0,-(a7)
 moveq.l #4-1,d0
 lea.l lastperiods-ms(a5),a0
setbacklaststuffto0:
   clr.l (a0)+
   move.w #$0100,(a0)+
   clr.w (a0)+
   clr.l (a0)+
   clr.l (a0)+
   clr.l (a0)+
   clr.l (a0)+
 dbra d0,setbacklaststuffto0
 moveq.l #4-1,d0
 lea.l lastvolumes-ms(a5),a0
setbacklastvolumes:
   clr.l (a0)+
  dbra d0,setbacklastvolumes
 movem.l (a7)+,d0/a0
 rts

_generalsndinit:               ; in d0 = oneshot(=<>0)
 movem.l d0-d7/a0-a6,-(a7)     ;    a1 = ptr to instr data
 lea.l mystructure(PC),a5      ;    a2 =        macros
 move.l a1,myinstrsdata-ms(a5) ;    a3 =        subroutine
 move.l a2,mymacrosdata-ms(a5) ;
 move.l a3,subroutine-ms(a5)
 bra internsndreset

ptrsinit:
 lea.l myinstrvecs-ms(a5),a0
 lea.l myinstrlens-ms(a5),a4
 move.l a5,-(a7)
 lea.l (INSTNUM*8)(a1),a5
 move.l a5,d4
 lea.l 4(a5),a5
 moveq.l #INSTNUM-1,d0
 moveq.l #0,d3
setinstlens:
 move.l a5,(a0)+
  move.w (a1)+,d3
  move.w d3,(a4)+
  adda.l d3,a5
   move.w (a1)+,(a4)+
   move.w (a1)+,(a4)+
   move.w (a1)+,(a4)+
 dbra d0,setinstlens
 move.l a5,d0
 btst.b #0,d0
 beq.s iseven1
  addq.l #1,d0
iseven1:
 move.l d0,a1
 move.l (a7)+,a5
 lea.l lfoinstptrs+4-ms(a5),a0
 move.l a5,-(a7)
 lea.l (15*2)(a1),a5
 moveq.l #15-1,d0
setuplfodata:
  move.l a5,(a0)+
  move.w (a1)+,d3
  adda.l d3,a5
 dbra d0,setuplfodata
 move.l (a7)+,a5
 moveq.l #(INSTNUM+1)-1,d0
 lea.l currlfotable-ms(a5),a0
clrcurrlfo:
   clr.l (a0)+
 dbra d0,clrcurrlfo
 move.l d4,defsndptr-ms(a5)
 move.l a2,-(a7)
 move.l a2,a0
 bsr searchmelodystrt
 bsr searchmelodystrt
 bsr searchmelodystrt
 bsr searchmelodystrt
 move.l a0,a1
 move.l a0,a2
 lea.l mymacrovecs-ms(a5),a0   ; OPTIONAL !
 move.w #997+1,d0
lookontostart:
 cmpi.b #$ff,(a1)
 beq.s setpausemacro
 cmpi.b #$fe,(a1)
 beq.s endofmacros
 move.l a1,(a0)+
 subq.w #1,d0
searchnext:
 addq.l #3,a1
 cmpi.b #$ff,(a1)
 bne.s searchnext
 addq.l #1,a1
 bra.s lookontostart
setpausemacro:
 move.l a2,(a0)+
 subq.w #1,d0
getnextmacro:
 addq.l #1,a1
 bra.s lookontostart
endofmacros:
 tst.w d0
 beq.s realendofmacros
   move.l a2,(a0)+
   subq.w #1,d0
   bra.s endofmacros
realendofmacros:
 move.l (a7)+,a2
melodystrtup:
 moveq.l #0,d1
 move.w (a2)+,d1
 moveq.l #0,d2
 move.w (a2)+,d2
 move.l a2,a0
 lea.l COUNTERS-ms(a5),a2
 lea.l mymacrovecs-ms(a5),a3  ; OPTIONAL
 lea.l MODUL_0-ms(a5),a1
 bsr.s writeandsearchmelodystrt
 lea.l MODUL_1-ms(a5),a1
 bsr.s writeandsearchmelodystrt
 lea.l MODUL_2-ms(a5),a1
 bsr.s writeandsearchmelodystrt
 lea.l MODUL_3-ms(a5),a1
 bsr.s writeonly
 lea.l strtvolus-ms(a5),a0
 lea.l volumetable-ms(a5),a1
 moveq.l #15,d0
strtupvolume:
   move.w (a0)+,(a1)+
  dbra d0,strtupvolume
 clr.w (a1)+
 clr.w (a1)+
 clr.w (a1)+
 clr.w (a1)+
 rts
writeandsearchmelodystrt:
 bsr.s writeonly
searchmelodystrt:
 cmpi.w #999,(a0)+
 bne.s searchmelodystrt
 rts
writeonly:
 move.l a2,16(a1)
 move.l a2,8(a1)
 addi.l #32,8(a1)
 move.l a0,12(a1)
 add.l d2,12(a1)
 add.l d2,12(a1)
 move.l a0,(a2)
 add.l d1,(a2)
 add.l d1,(a2)
 move.l (a2),a4
 move.w (a4),d0
 add.w d0,d0
 add.w d0,d0
 move.l 0(a3,d0.w),16(a2)
 move.w #1,32(a2)
 clr.l 32+16(a2)
 addq.l #4,a2
 rts

hardwareinit:
 lea.l $dff000,a6
 move.w #$000f,$96(a6)
 moveq.l #0,d0
 move.w d0,$0a8(a6)
 move.w d0,$0b8(a6)
 move.w d0,$0c8(a6)
 move.w d0,$0d8(a6)
 rts

_setspeed:  ; speed (300-2800), returns old speed in d0
 movem.l d1/a5,-(a7)
 lea.l mystructure(PC),a5
 move.w speed-ms(a5),d1
 move.w d0,speed-ms(a5)
 bsr.s getfacttruncedspeed
 move.w d0,calcspeed-ms(a5)
 mulu #23,d0
 move.w d0,playspeed-ms(a5)
 move.w d1,d0
 movem.l (a7)+,d1/a5
 rts

getfacttruncedspeed:
 mulu curspeedfact1-ms(a5),d0
 divu curspeedfact2-ms(a5),d0
 cmpi.w #300,d0
 bge.s speedover300
  move.w #300,d0
speedover300:
 cmpi.w #2800,d0
 ble.s speedbelow2800
  move.w #2800,d0
speedbelow2800:
 rts

_setvolume:    ; d0=state(0-127)
 movem.l d1-d2/a0-a2/a5,-(a7)
 andi.w #$007f,d0
  lea.l mystructure(PC),a5
  lea.l volumetable-ms+2(a5),a0
  lea.l strtvolus-ms+2(a5),a1
  moveq.l #(16-1)-1,d2
setvolloop:
    move.w (a1)+,d1
    mulu d0,d1
    lsr.w #7,d1
    move.w d1,(a0)+
  dbra d2,setvolloop
 moveq.l #4-1,d2
setvolloop1:
   move.w 8(a0),d1
   add.w d1,d1
   mulu d0,d1
   lsr.w #7,d1
   move.w d1,(a0)+
 dbra d2,setvolloop1
 movem.l (a7)+,d1-d2/a0-a2/a5
 rts

_decrunchinstrs:           ; a0=source , a1=dest
 lea.l mystructure(PC),a5
 move.l a0,a3
 moveq.l #INSTNUM-1,d0
copyinstlens:
  move.l (a0)+,(a1)+
  move.l (a0)+,(a1)+
 dbra d0,copyinstlens
 clr.l (a1)+
 move.w (a0)+,fibbits-ms(a5)
 move.l a0,fibtable-ms(a5)
 move.w fibbits-ms(a5),d0
 moveq.l #1,d1
 lsl.w d0,d1
 lea.l 0(a0,d1.w),a0
 moveq.l #INSTNUM-1,d7
packinstrsloop:
   moveq.l #0,d0
   move.w (a3),d0
    beq.s leniszero1
   moveq.l #0,d2
   move.w fibbits-ms(a5),d2
   jsr decompress(PC)
leniszero1:
 addq.l #8,a3
 dbra d7,packinstrsloop
 move.l a1,d0
 btst.b #0,d0
 beq.s iseven
  addq.l #1,d0
iseven:
 move.l d0,a1
 moveq.l #(15*2)-1,d0
 move.l a1,a2
copylfodata:
  move.b (a0)+,(a1)+
 dbra d0,copylfodata
 moveq.l #15-1,d0
copylfodatalong:
  move.w (a2)+,d1
  beq.s lfoisunset
   subq.w #1,d1
copylfodatainner:
     move.b (a0)+,(a1)+
    dbra d1,copylfodatainner
lfoisunset:
 dbra d0,copylfodatalong
 rts

decompress:
  movem.l d0-d7/a2-a3,-(a7)
  move.l a0,a3
  move.l fibtable-ms(a5),a0
  lea.l 0(a1,d0.l),a2
  move.l d2,d0
  moveq.l #0,d6
  moveq.l #0,d7
  moveq.l #0,d2
1$:
   moveq.l #0,d1
   move.w d0,d3
2$:
    subq.w #1,d7
    bpl.s 3$
     move.b (a3)+,d6
     moveq.l #7,d7
3$:
    lsl.b #1,d6
    addx.b d1,d1
    subq.w #1,d3
   bne.s 2$
   add.b 0(a0,d1.w),d2
   move.b d2,(a1)+
  cmpa.l a1,a2
  bne.s 1$
 subq.w #1,d7
 bpl.s 4$
   addq.l #1,a3
4$:
 move.l a3,a0
 movem.l (a7)+,d0-d7/a2-a3
 rts

_generalplay:
 movem.l d0-d7/a0-a6,-(a7)
 lea.l $dff000,a6
 lea.l mystructure(PC),a5
 tst.b soundenable-ms(a5)
 bne.s noplay
 cmpi.b #$0f,_channelsfinished-ms(a5)
 beq.s noplay
   bsr.s playsnd
noplay:
 movem.l (a7)+,d0-d7/a0-a6
 rts

playsnd:          ; in a6=dff000, a5=mystructure
 move.w playspeed-ms(a5),d0
 tst.w whattodo-ms(a5)
 beq.s contsound
  clr.w whattodo-ms(a5)
  sub.w resttime-ms(a5),d0
  subi.w #$170,d0
  bsr settimer
  bra donthavetowait
contsound:
 bsr settimer
 clr.b ((dmaoff-ms)+1)(a5)
 clr.b ((dmaon-ms)+1)(a5)
 moveq.l #0,d2
 move.b _fadeflag-ms(a5),d2
 beq.s nooutfade
   lea.l volumetable-ms(a5),a0
   cmpi.w #3,2*15(a0)
   bgt.s fadenotfinished
    st _fadefinished-ms(a5)
    bra.s nooutfade
fadenotfinished:
    addq.l #2,a0
     moveq.l #(16-1)-1,d0
fadeloop:
      move.w (a0),d1
      mulu d2,d1
      lsr.w #7,d1
      move.w d1,(a0)+
     dbra d0,fadeloop
    moveq.l #4-1,d0
fadeloop1:
      move.w (a0),d1
      asr.w #1,d1
      mulu d2,d1
      lsr.w #6,d1
      move.w d1,(a0)+
     dbra d0,fadeloop1
nooutfade:
 lea.l $d0(a6),a0
 lea.l ((lastvolumes-ms)+6)(a5),a1
 move.w volumetable+(15*2)-ms(a5),d7
 lea.l ((lastperiods-ms)+(24*3))(a5),a4
 lea.l modultable-ms(a5),a2
 lea.l SOFTMOD+(3*4)-ms(a5),a3
 sf channelshandle-ms(a5)
 moveq.l #3,d0
setallchanneldata:
 move.w (a2)+,d1
 movem.l a0-a4/d0/d7,-(a7)
 movem.l 0(a5,d1.w),d3/d7/a2-a4
 bsr handle_channel
 movem.l (a7)+,a0-a4/d0/d7
 movem.l a2,-(a7)
  tst.l d4
  bmi.s absnothing
  tst.l d5
  bmi.s pervolonly
   bset.b d0,channelshandle-ms(a5)
   move.w d4,4(a0)
   move.l d5,(a0)
    swap d4
    move.w d4,d3
    swap d4
    lsr.w #8,d3
    lsl.w #2,d3
    clr.w 18(a4)
    lea.l currlfotable-ms(a5),a2
    move.l 0(a2,d3.w),8(a4)
     beq.s skiphull
    st 18(a4)
    clr.w 14(a4)
    move.w d4,16(a4)
    lsl.w 16(a4)
skiphull:
pervolonly:
  rol.w #8,d6
  move.b d6,9(a1)
  lsr.w #8,d6
  add.w d6,d6
  move.w d6,(a1)
  swap d6
  move.w d6,(a4)
  swap d4
  andi.w #$00ff,d4
  move.w d4,2(a4)
  moveq.l #-1,d4
absnothing:
  tst.w d4
  bmi.s nosetfade2
   move.w d4,4(a4)
nosetfade2:
  btst.b d0,dofadein-ms(a5)
  beq.s testiffadeout
    cmpi.w #4096,4(a4)
    bls.s donotsetbackto4096
      move.w #4096,4(a4)
donotsetbackto4096:
    cmpi.w #256,4(a4)
    beq.s nomorefade
    blt.s setbackto256
     move.w fadespeedin-ms(a5),d1
     sub.w d1,4(a4)
     bra.s nomorefade
setbackto256:
    move.w #256,4(a4)
    bra.s nomorefade
testiffadeout:
  btst.b d0,dofadeout-ms(a5)
  beq.s nomorefade
    cmpi.w #8192,4(a4)
    beq.s nomorefade
    bgt.s setbackto8192
     move.w fadespeedout-ms(a5),d1
     add.w d1,4(a4)
     bra.s nomorefade
setbackto8192:
    move.w #8192,4(a4)
nomorefade:
  move.w 8(a1),d6
  move.w 2(a3),d1
  asr.w #1,d1
  add.w d1,d6
  moveq.l #64,d1
  exg d1,d7
  bsr getalegalvolume
  exg d1,d7
  move.w d6,8(a1)
  move.w (a1),d6
  add.w 2(a3),d6
  add.w d7,d7
  bsr getalegalvolume
  lsr.w #1,d7
  move.w d6,(a1)
  lsr.w #1,d6
  tst.b 18(a4)
  beq.s nuHULL
   moveq.l #0,d1
   move.w 14(a4),d1
   divu #40,d1
   swap d1
   clr.w d1
   swap d1
   add.w d1,d1
   add.l 8(a4),d1
   move.l d1,a2
   move.b 1(a2),d3
   move.b (a2)+,d1
    beq.s nuHULL
   ext.w d1
   muls d6,d1
   asr.w #5,d1
  add.w d1,d6
  bsr getalegalvolume
nuHULL:
  btst.b d0,doloudness-ms(a5)
  beq.s nodoloudness
     move.w 2(a4),d4
     moveq.l #0,d5
     lsl.w #8,d6
     move.w d6,d5
     lea.l loudnesstable-ms(a5),a2
     divu.w 0(a2,d4.w),d5
      cmp.w d6,d5
      bne.s writeloudnessvolume
        moveq.l #0,d5
writeloudnessvolume:
    move.w d5,d6
nodoloudness:
 cmpi.w #$0100,4(a4)
 beq.s nofadeatall
  lsl.w #8,d6
  moveq.l #0,d5
  move.w d6,d5
  divu 4(a4),d5
   cmp.w d6,d5
   bne.s checkvol
    moveq.l #0,d5
checkvol:
  move.w d5,d6
nofadeatall:
  bsr getalegalvolume
  move.w d6,8(a0)       ; - - - VOLUME READY !
  move.w (a4),d6
  add.w (a3),d6
  bsr getalegalperiod
  move.w d6,(a4)
  tst.b 18(a4)
  beq.s nuHULLEND
   tst.b d3
   beq.s noLFOper
   ext.w d3
   move.w d6,d2
   muls.w d3,d2
   asr.l #8,d2
   add.w d2,d6
   bsr getalegalperiod  ; - - - PERIOD READY !
noLFOper:
   move.w calcspeed-ms(a5),d1
   mulu #115,d1
   divu d6,d1
   add.w d1,14(a4)
   move.w 14(a4),d1
   cmp.w 16(a4),d1
   bls.s nuHULLEND
    tst.b 19(a4)
     beq.s switchoffHULL
      move.w 20(a4),d1
      sub.w d1,14(a4)
      bra.s nuHULLEND
switchoffHULL:
       sf 18(a4)
nuHULLEND:
  move.w d6,6(a0)
 subq.l #2,a1
 subq.l #4,a3
 lea.l -24(a4),a4
 movem.l (a7)+,a2
 lea.l -$10(a0),a0
 dbra d0,setallchanneldata

 tst.b channelshandle-ms(a5)
 beq.s donthavetowait
 move.w dmaon-ms(a5),d0
 and.w dmaoff-ms(a5),d0
 beq.s donthavetowait
    st whattodo-ms(a5)
    lea.l $bfd000,a0
    andi.b #%10011110,$f00(a0)
     move.b $700(a0),d0
      lsl.w #8,d0
       move.b $600(a0),d0
        move.w playspeed-ms(a5),d1
        sub.w d0,d1
        move.w d1,resttime-ms(a5)
    move.w #$0170,d0
    bra settimer
donthavetowait:
 move.w dmaon-ms(a5),$096(a6)
 move.b _channelsfinished-ms(a5),d3
 bne.s waitatimee
  tst.b channelshandle-ms(a5)
  beq.s exitplay
waitatimee:
   btst.b #0,$006(a6)
   bne.s wait555
wait444:
   btst.b #0,$006(a6)
   beq.s wait444
   bra.s wait666
wait555:
   btst.b #0,$006(a6)
   bne.s wait555
wait666:
   btst.b #4,$007(a6)
   beq.s wait666
     lea.l $d0(a6),a1
     lea.l nextdata3-ms(a5),a2
     lea.l lastperiods+(24*3)-ms(a5),a3
     moveq.l #3,d2
testifcontinsts:
      btst.b d2,d3
      bne.s pause_0
       btst.b d2,channelshandle-ms(a5)
       beq.s nopause_0
         move.l (a2),(a1)
         move.w 4(a2),4(a1)
         tst.b 18(a3)
         beq nopause_0
         move.l (a2),d0
         cmp.l defsndptr-ms(a5),d0
         beq nopause_0
          st 19(a3)
          move.w 4(a2),20(a3)
          lsl.w 20(a3)
         bra.s nopause_0
pause_0:
         move.l defsndptr-ms(a5),(a1)
         move.w #1,4(a1)
nopause_0:
       lea.l -$10(a1),a1
       subq.l #8,a2
       lea.l -24(a3),a3
     dbra d2,testifcontinsts
exitplay:
 tst.b calltheroutine-ms(a5)
 beq.s donotcall
  movem.l d0-d7/a0-a6,-(a7)
  sf calltheroutine-ms(a5)
  move.l subroutine-ms(a5),d0
  beq.s endofcall
    move.l d0,a0
    addq.w #1,called-ms(a5)
    move.w called-ms(a5),d0
     jsr (a0)
endofcall:
    movem.l (a7)+,d0-d7/a0-a6
donotcall:
 rts

getalegalvolume:
  tst.w d6
  bpl.s noprbwithVOL
     clr.w d6
noprbwithVOL:
  cmp.w d7,d6
  ble.s noprbwithVOL1
    move.w d7,d6
noprbwithVOL1:
  rts

getalegalperiod:
  cmpi.w #113,d6
  bge.s noprbwithPER
   move.w #113,d6
noprbwithPER:
  cmpi.w #856,d6
  ble.s noprbwithPER1
   move.w #856,d6
noprbwithPER1:
  rts

settimer:
  lea.l $bfd000,a0
  move.b #%00000010,$d00(a0)
  andi.b #%10011100,$f00(a0)
   move.b d0,$600(a0)
    lsr.w #8,d0
      move.b d0,$700(a0)
  ori.b #%00011101,$f00(a0)
  move.b #%10000010,$d00(a0)
  rts

handle_channel:
 subq.w #1,(a2)
 beq.s countatzero
donothingwithDMA:
   moveq.l #-1,d4
   rts
countatzero:
 move.b internfinished-ms(a5),d0
 and.b d7,d0
 beq.s normalplay
  not.w d7
  and.b d7,dofadein-ms(a5)
  and.b d7,dofadeout-ms(a5)
  not.w d7
  move.w #0,8(a0)
  clr.w (a1)
  clr.w 8(a1)
  move.w d7,$096(a6)
  move.l 28(a7),a1
  clr.l (a1)+
  move.w #$0100,(a1)+
  clr.w (a1)+
  clr.l (a1)+
  clr.l (a1)+
  clr.l (a1)+
  clr.l (a1)+
  tst.b oneshot-ms(a5)
  beq.s normalplay1
   or.b d7,_channelsfinished-ms(a5)
   bra.s donothingwithDMA
normalplay1:
 not.w d7
 and.b d7,internfinished-ms(a5)
 not.w d7
normalplay:
 move.l 16(a4),a0

 move.b 2(a0),d0
 cmpi.b #$f2,3(a0)
 beq.s takenextascount
 cmpi.b #$fb,3(a0)
 beq.s takenextascount
 cmpi.b #$f8,(a0)
 bne.s isbelow15
takenextascount:
   move.b 2+3(a0),d0
isbelow15:
 andi.w #$003f,d0
 addq.w #1,d0
 add.w d0,d0
 move.w d0,(a2)

; clr.l 32+16(a4)
 moveq.l #0,d5
 move.b (a0),d0
 move.b 1(a0),d1
 cmpi.b #$f2-1,d0
 bls nocontrolbyte
 cmpi.b #$f4,d0
 bne.s noloudness
  not.w d7
  and.b d7,doloudness-ms(a5)
  not.w d7
   tst.b d1
   beq.s OFFloudness
    or.b d7,doloudness-ms(a5)
OFFloudness:
jmptoaddcnt:
      moveq.l #-1,d4
      bra addcounthandle
noloudness:
 cmpi.b #$fd,d0
 beq.s jmptoaddcnt
 cmpi.b #$f5,d0
 bne.s nocustomprg
   st calltheroutine-ms(a5)
   bra.s jmptoaddcnt
nocustomprg:
 cmpi.b #$f6,d0
  bne.s nofade
   not.w d7
   and.b d7,dofadein-ms(a5)
   and.b d7,dofadeout-ms(a5)
   not.w d7
   tst.b d1
   beq.s jmptoaddcnt
   bmi.s switch2in
switch2out:
   move.b d1,fadespeedout+1-ms(a5)
   or.b d7,dofadeout-ms(a5)
   bra.s jmptoaddcnt
switch2in:
   neg.b d1
   move.b d1,fadespeedin+1-ms(a5)
   or.b d7,dofadein-ms(a5)
   bra.s jmptoaddcnt
nofade:
 cmpi.b #$f7,d0
 bne.s nosetfadestate
   moveq.l #-1,d4
   tst.b d1
   beq.s settoLO
settoHI:
   move.w #256,d4
    bra addcounthandle
settoLO:
   move.w #8192,d4
    bra addcounthandle
nosetfadestate:
 cmpi.b #$f8,d0
 bne.s isbelow151
   move.b d1,d5
   addq.l #3,a0
   move.b (a0),d0
   move.b 1(a0),d1
isbelow151:
 cmpi.b #$f9,d0
 bne.s noWARP
   ext.w d1
   btst.b #7,2(a0)
   beq.s PERWARP
     move.w d1,32+16+2(a4)
     bra jmptoaddcnt
PERWARP:
   move.w d1,32+16(a4)
   bra jmptoaddcnt
noWARP:
 cmpi.b #$fa,d0
 bne.s nosetuphull
   move.b d1,d2
   andi.w #$00f0,d1
   lsr.b #4,d1
   add.b d5,d1
   andi.w #$000f,d2
   lsl.b #2,d2
   lea.l lfoinstptrs-ms(a5),a1
   move.l 0(a1,d2.w),d2
    beq.s clrlfoptr
   move.l d2,a1
   addq.l #2,d2
   cmp.w (a1),d1
   beq.s proper
clrlfoptr:
     moveq.l #0,d2
proper:
   lsl.w #2,d1
   lea.l currlfotable-ms(a5),a1
   move.l d2,0(a1,d1.w)
   bra jmptoaddcnt
nosetuphull:
 cmpi.b #$fc,d0
 bne.s nospeedset
   moveq.l #0,d0
   move.b d1,d0
   lsr.w #4,d0
   andi.w #$000f,d1
   move.w d0,curspeedfact1-ms(a5)
   move.w d1,curspeedfact2-ms(a5)
   mulu.w speed-ms(a5),d0
   divu d1,d0
    cmpi.w #300,d0
    bge.s speedover300A
      move.w #300,d0
speedover300A:
    cmpi.w #2800,d0
    ble.s speedbelow2800A
      move.w #2800,d0
speedbelow2800A:
   move.w d0,calcspeed-ms(a5)
   mulu #23,d0
   move.w d0,playspeed-ms(a5)
   move.l a0,-(a7)
   bsr settimer
   move.l (a7)+,a0
   bra jmptoaddcnt
nospeedset:
nocontrolbyte:
 clr.l 32+16(a4)
 btst.b #6,2(a0)
 beq.s nochangelpfplay
   move.b d1,d2
   andi.b #$40,d2
   lsr.b #5,d2
   andi.b #$fd,$bfe001
   or.b d2,$bfe001
nochangelpfplay:
 moveq.l #0,d4
 andi.w #$003f,d1
 add.w d1,d1
 move.w d1,d4
 swap d4
 move.w notetable-ms(a5,d1.w),d6
 swap d6

 cmpi.b #$f1,d0
  bne.s nonovolume
novolume:
      clr.w d6
      move.w d7,$096(a6)
      or.w d7,dmaoff-ms(a5)
      moveq.l #INSTNUM,d4
      ror.l #8,d4
      move.w #1,d4
      move.l defsndptr-ms(a5),d5
      move.l d5,0(a5,d3.w)
      move.w d4,4(a5,d3.w)
      bra addcounthandle
modulate:
      moveq.l #-1,d5
      moveq.l #0,d0
      cmpi.b #$f2,3(a0)
      beq.s losoftmod
      cmpi.b #$fb,3(a0)
      bne addcounthandle
      moveq.l #1,d0
losoftmod:
      move.b 3+1(a0),d1
      moveq.l #0,d2
      moveq.l #4,d3
      move.b d1,d2
      asr.b d3,d1
      ext.w d1
      lsl.b d3,d2
      asr.b d3,d2
      ext.w d2
      asl.w d0,d2
      move.w d2,32+16(a4)
      move.w d1,32+16+2(a4)
      addq.l #3,a0
      bra addcounthandle
nonovolume:
 andi.w #$000f,d0
 beq.s novolume
 add.w d0,d0
 lea.l strtvolus-ms(a5),a1
 move.w 0(a1,d0.w),d6
 lsl.w #8,d6
 move.b volumetable-ms+1(a5,d0.w),d6
 btst.b #7,2(a0)
  bne.s modulate

 move.b (a0),d2
 andi.w #$00f0,d2
 lsr.w #4,d2
 add.b d5,d2
 swap d4
 rol.w #8,d4
 move.b d2,d4
 rol.w #8,d4
 swap d4
 lsl.w #2,d2
 move.l myinstrvecs-ms(a5,d2.w),d5
 add.w d2,d2

 move.w d7,$096(a6)
 or.w d7,dmaoff-ms(a5)
 or.w d7,dmaon-ms(a5)

 lea.l myinstrlens-ms(a5),a1
 tst.w 0(a1,d2.w)
 beq novolume
 btst.b #7,1(a0)
 beq.s setoneshotdata
     move.l d5,0(a5,d3.w)
     moveq.l #0,d0
     move.w 4(a1,d2.w),d0
     add.l d0,0(a5,d3.w)
     move.w 6(a1,d2.w),4(a5,d3.w)
     move.w 2(a1,d2.w),d4
     bra.s setrestdata
setoneshotdata:
     move.l defsndptr-ms(a5),0(a5,d3.w)
     move.w #1,4(a5,d3.w)
     move.w 0(a1,d2.w),d4
setrestdata:
     lsr.w #1,d4
addcounthandle:
 addq.l #3,a0
  cmpi.b #$f3,(a0)
  bne.s nosoftmodpseudo
   addq.l #6,a0
nosoftmodpseudo:
 cmpi.b #$ff,(a0)
 bne.s nonewmacro
   bsr.s getnewmacro
   tst.w d1          ; am ENDE kein ueberklingen !
   beq.s nonewmacro
    cmpi.b #$f0,(a0)
    bne.s nonewmacro
      move.b 2(a0),d0
      andi.w #$003f,d0
      addq.w #1,d0
      add.w d0,d0
      add.w d0,(a2)
      bra.s addcounthandle
nonewmacro:
 move.l a0,16(a4)
 rts

getnewmacro:
 moveq.l #1,d1
 addq.l #2,(a4)
 move.l (a4),a1
 tst.w (a1)
 bne.s nopause2play
   move.w pattlen-ms(a5),d1
   add.w d1,d1
   add.w d1,(a2)
   bra.s getnewmacro
nopause2play:
 cmpi.w #999,(a1)
  bne.s no_melody_carry
    move.l a3,(a4)
    move.l a3,a1
    moveq.l #0,d1
    or.b d7,internfinished-ms(a5)
no_melody_carry:
 move.w (a1),d0
 lsl.w #2,d0
 lea.l mymacrovecs-ms(a5),a1  ; OPTIONAL
 move.l 0(a1,d0.w),a0
 rts

; required data
; -----

 dc.b 'music by MusicMakerV8/4 CHANNEL VERSION - - '
 dc.b 'Written by DIRE CRACKS Inc.',$0d,$0a
 cnop 0,2

notetable:         dc.w 856,832,808,784,760,740,720,700,680,660,640,622
                   dc.w 604,588,572,556,540,524,508,494,480,466,452,440
                   dc.w 428,416,404,392,380,370,360,350,340,330,320,311
                   dc.w 302,294,286,278,270,262,254,247,240,233,226,220
                   dc.w 214,208,202,196,190,185,180,175,170,160,151,143
                   dc.w 135,127,120,113
mystructure: ; -0-
ms:
volumetable:       dc.w 0,1,2,3,5,7,11,16,22,28,34,40,46,52,58,64
lastvolumes:       dc.w 0,0,0,0,0,0,0,0    ;(nichts dazwischen !)
myinstrvecs:       ds.l INSTNUM
myinstrlens:       ds.w INSTNUM*8
strtvolus:         dc.w 0,1,2,3,5,7,11,16,22,28,34,40,46,52,58,64
speed:             dc.w 0
playspeed:         dc.w 0
curspeedfact1:     dc.w 1
curspeedfact2:     dc.w 1
pattlen:           dc.w 0
whattodo:          dc.w 0
resttime:          dc.w 0
dmaoff:            dc.w $0000
dmaon:             dc.w $8000
fadespeedin:       dc.w 63
fadespeedout:      dc.w 21
channelshandle:    dc.b 0
internfinished:    dc.b 0
oneshot:           dc.b 0
_channelsfinished: dc.b 0
soundenable:       dc.b -1
_fadeflag:         dc.b 0
_fadefinished:     dc.b 0
doloudness:        dc.b 0
calltheroutine:    dc.b 0
dofadein:          dc.b 0
dofadeout:         dc.b 0
 cnop 0,2
defsndptr:         dc.l 0
subroutine:        dc.l 0
called:            dc.w 0
lfoinstptrs:       ds.l 16         ; N.T.P.I. !!!
currlfotable:      ds.l INSTNUM+1  ;
calcspeed:         dc.w 0
nextdata0:         dc.l 0,0
nextdata1:         dc.l 0,0
nextdata2:         dc.l 0,0
nextdata3:         dc.l 0,0
modultable:        dc.w MODUL_3-ms,MODUL_2-ms,MODUL_1-ms,MODUL_0-ms
MODUL_0:           dc.l nextdata0-ms,1,0,0,0
MODUL_1:           dc.l nextdata1-ms,2,0,0,0
MODUL_2:           dc.l nextdata2-ms,4,0,0,0
MODUL_3:           dc.l nextdata3-ms,8,0,0,0
COUNTERS:          dc.l 0,0,0,0                               ; NOTHING TO
MACRO_C:           dc.l 0,0,0,0                               ; BE PUT
SCOUNT:            dc.w 1,0,1,0,1,0,1,0                       ; INBETWEEN !
SOFTMOD:           dc.l 0,0,0,0                               ; !!!
lastperiods:       dc.l 0,0,0,0,0,0
                   dc.l 0,0,0,0,0,0
                   dc.l 0,0,0,0,0,0
                   dc.l 0,0,0,0,0,0
myinstrsdata:      dc.l 0
mymacrosdata:      dc.l 0
loudnesstable:
 dc.w 256,264,268,273,277,287,292,297,303,309,315,321,327,334,341
  dc.w 348,356,364,372,372,381,390,399,399
 dc.w 409,420,420,431,431,442,442,455,468,468,468,481,481,481,496
  dc.w 496,496,512,512,512,512,512,512,512
 dc.w 512,512,512,512,511,511,511,511,511,511,511,511,511,511,511
  dc.w 511
 cnop 0,2
fibbits:           dc.w 0
fibtable:          dc.l 0
mymacrovecs:       ds.l 999 ; optional (can be somewhere in memory also!)
                            ;          (then set a pointer here instead,
                            ;          (and replace the "lea.l mymacro..."
                            ;          (by "move.l mymacrovecs..."
 END



