home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 1 / GoldFishApril1994_CD2.img / d4xx / d483 / med / med.lzh / MED / Programmers / MODPlayer / easyplayer.a < prev    next >
Text File  |  1991-05-08  |  50KB  |  1,772 lines

  1. ;    easyplayer.a -    A simple-to-use 4-channel MED3.10/OctaMED1.00
  2. ;            player routine
  3. ;    Written by Teijo Kinnunen.
  4.  
  5. ;    Works on Devpac 2 assembler
  6. ;    Type in the name of your module to the INCBIN statement.
  7. ;    Call _startmusic at the beginning, _endmusic at the end.
  8.  
  9. ac_ptr    EQU    $00
  10. ac_len    EQU    $04
  11. ac_per    EQU    $06
  12. ac_vol    EQU    $08
  13. T03SZ    EQU    74
  14. T415SZ    EQU    18
  15.  
  16. MIDI    EQU    0    ;1 = include MIDI code
  17. AUDDEV    EQU    1    ;1 = allocate channels using audio.device
  18. SYNTH    EQU    1    ;1 = include synth-sound handler
  19. CHECK    EQU    1    ;1 = do range checkings (track, sample in mem etc.)
  20. RELVOL    EQU    1    ;1 = include relative volume handling code
  21. IFF53    EQU    1    ;1 = play IFF 3- and 5-octave samples correctly
  22. ;****** Timing control ******
  23. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  24. CIAB    EQU    1    ;1 = use CIAB timers (default)
  25. ; Please use CIAB whenever possible to avoid problems with variable
  26. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  27. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  28. ; then you just call _IntHandler for each timing pulse.
  29.  
  30.         section    "text",code
  31.  
  32. _ChannelOff:    ;d0 = channel #
  33.         lea    trackdataptrs(pc),a1
  34.         lsl.b    #2,d0
  35.         adda.w    d0,a1
  36.         lsr.b    #2,d0
  37.         movea.l    (a1),a1
  38.     IFNE    MIDI
  39.         move.b    trk_prevmidin(a1),d1    ;first: is it MIDI??
  40.         beq.s    notcomidi    ;not a midi note
  41. choff_midi:    clr.b    trk_prevmidin(a1)
  42.         lea    noteondata(pc),a0
  43.         move.b    d1,1(a0)
  44.         move.b    trk_prevmidich(a1),(a0)    ;prev midi channel
  45.         clr.b    2(a0)
  46.         or.b    #$90,(a0)        ;note off
  47.         moveq    #3,d0
  48.         bra.w    _AddMIDIData
  49. notcomidi:
  50.     ENDC
  51.         cmp.b    #4,d0
  52.         bge.s    notamigatrk
  53.     IFNE    SYNTH
  54.         clr.l    trk_synthptr(a1)
  55.         clr.b    trk_synthtype(a1)
  56.     ENDC
  57.         moveq    #1,d1
  58.         lsl.w    d0,d1
  59.         move.w    d1,$dff096
  60. notamigatrk:    rts
  61.  
  62. SoundOff:    move.l    d2,-(sp)
  63.         moveq    #15,d2
  64. SO_loop0    move.l    d2,d0
  65.         bsr.s    _ChannelOff
  66.         dbf    d2,SO_loop0
  67.         lea    _module(pc),a0
  68.         clr.l    (a0)        ;play nothing!!
  69.         move.l    (sp)+,d2
  70.         rts
  71.  
  72. _PlayNote:    ;d0(w) = trk #, d1 = note #, d2 = vol, d3(w) = instr # a3 = addr of instr
  73.         movem.l d3-d7,-(sp) ;All right, let's start!!
  74.         move.w    d2,-(sp)
  75.         moveq    #0,d4
  76.         bset    d0,d4    ;d4 is mask for this channel
  77.         movea.l    24(a6),a0    ;ptr to sample array
  78.         move.w    d3,d7
  79.         add.w    d3,d3            ;d3 = instr.num << 2
  80.         add.w    d3,d3
  81.         move.l    0(a0,d3.w),d5        ;get address of instrument
  82.     IFNE    MIDI
  83.         bne.s    inmem
  84.         tst.b    4(a3)            ;is MIDI channel set
  85.     ENDC
  86.     IFNE    CHECK
  87.         beq.w    retsn2            ; NO!!!
  88.     ENDC
  89. inmem:        add.b    766(a4),d1    ;add play transpose
  90.         add.b    7(a3),d1    ;and instr. transpose
  91.         cmp.b    #4,d0
  92.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  93.         move.l    d5,a1
  94.     IFNE    SYNTH
  95.         tst.l    d5        ;is there sample in memory?
  96.         beq.s    stpdma
  97.         tst.b    trk_synthtype(a5)
  98.         ble.s    stpdma
  99.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  100.         beq.s    nostpdma
  101.     ENDC
  102. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  103. nostpdma:
  104.     IFNE    SYNTH
  105.         clr.l    trk_synthptr(a5)
  106.     ENDC
  107. nodmaoff:
  108.     IFNE    MIDI
  109.         move.b    trk_prevmidin(a5),d6    ;get prev. midi note
  110.         beq.s    noprevmidi
  111.         clr.b    trk_prevmidin(a5)
  112.         lea    noteondata(pc),a0
  113.         move.b    d6,1(a0)
  114.         move.b    trk_prevmidich(a5),(a0)    ;prev midi channel
  115.         or.b    #$90,(a0)        ;note off
  116.         clr.b    2(a0)        ;clear volume
  117.         movem.w    d0-d1,-(sp)
  118.         moveq    #3,d0
  119.         bsr.w    _AddMIDIData
  120.         movem.w    (sp)+,d0-d1
  121. noprevmidi:    tst.b    4(a3)
  122.         bne.w    handleMIDInote
  123.     ENDC
  124.     IFNE    CHECK
  125.         cmp.w    #4,d0        ;track > 3???
  126.         bge.w    retsn2        ;no Amiga instruments here!!!
  127.     ENDC
  128. ; handle decay (for tracks 0 - 3 only!!)
  129.         clr.b    trk_fadespd(a5)        ;no fade yet..
  130.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  131.         clr.b    trk_vibroffs(a5)    ;clr vibrato offset
  132.         or.w    d4,dmaonmsk
  133.         move.l    d5,a0
  134.         subq.b    #1,d1
  135.     IFNE    SYNTH
  136.         tst.w    4(a0)
  137.         bmi.w    handleSynthnote
  138.         clr.b    trk_synthtype(a5)
  139.     ENDC
  140. tlwtst0:    tst.b    d1
  141.         bpl.s    notenot2low
  142.         add.b    #12,d1    ;note was too low, octave up
  143.         bra.s    tlwtst0
  144. notenot2low:    cmp.b    #62,d1
  145.         ble.s    endpttest
  146.         sub.b    #12,d1    ;note was too high, octave down
  147. endpttest:    move.w    d0,d4    ;d4 = track number
  148.         bsr.w    getinsdata
  149.         movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  150.         move.w    (sp),ac_vol(a1)
  151.         add.w    d4,d4    ;d4 = trk << 1
  152.         move.w    d4,d6
  153.         add.w    d6,d6    ;d6 = trk << 2
  154.         move.l    d0,ac_ptr(a1)        ;put it in ac_ptr
  155.         cmp.w    #1,d3
  156.         bhi.s    repeat
  157.         
  158.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  159.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  160.         lsr.l    #1,d1            ;shift length right
  161.         move.w    d1,ac_len(a1)        ;and put to custom chip
  162.         bra.s    retsn1
  163.  
  164. repeat:        tst.w    d2
  165.         beq.s    begin0        ;rep. start < 2
  166.         move.w    d2,ac_len(a1)    ;move repeat to hardware
  167.         bra.s    beginn0
  168. begin0:        move.w    d3,ac_len(a1)
  169. beginn0:    lsl.l    #1,d2        ;shift
  170.         add.l    d2,d0        ;d0 = starting address of repeat
  171.         move.l    d0,trk_sampleptr(a5)    ;remember rep. start
  172.         move.w    d3,trk_samplelen(a5)    ;remember rep. length
  173.                 
  174. retsn1:        move.w    d5,ac_per(a1)    ;getinsdata puts period to d5
  175.         move.w    d5,trk_prevper(a5)
  176.     IFNE    SYNTH
  177.         tst.b    trk_synthtype(a5)
  178.         bne.w    hSn2
  179.     ENDC
  180. retsn2:        addq.l    #2,sp    ;forget volume
  181.         movem.l    (sp)+,d3-d7
  182.         rts
  183.  
  184.     IFNE    MIDI
  185. handleMIDInote:
  186.         lea    noteondata(pc),a0
  187.         add.b    #23,d1        ;2 octaves higher and -1
  188.         bpl.s    mnot2low    ;note number not too low
  189.         add.b    #12,d1        ;it was too low, 1 octave up
  190.         bra.s    endmtst
  191. mnot2low:    tst.b    d1        ;is it too high then??
  192.         bpl.s    endmtst        ;no, not greater than 127
  193.         sub.b    #12,d1        ;1 octave down, if yes
  194. endmtst:    move.b    d1,1(a0)    ;MIDI msg note #
  195.         move.b    d1,trk_prevmidin(a5)    ;save this note number
  196.         move.b    d2,d4        ;temporary save the volume
  197.         subq.b    #1,d2        ;if 64 => 63
  198.         bpl.s    nooops
  199.         moveq    #0,d2        ;oops, too low!!
  200. nooops:        lsl.b    #1,d2        ;volume 0 - 63 => 0 - 127
  201.         bclr    #7,d2        ;be sure that bit 7 is clear
  202.         move.b    d2,2(a0)    ;MIDI msg volume
  203.         moveq    #0,d1
  204.         move.b    4(a3),d1    ;get midi chan of this instrument
  205.         subq.b    #1,d1        ;from 1-16 to 0-15
  206.         move.b    d1,trk_prevmidich(a5)    ;save to prev midi channel
  207.         move.b    #$90,(a0)    ;MIDI: Note on
  208.         or.b    d1,(a0)        ;MIDI msg Note on & channel
  209.         move.b    5(a3),d2    ;get preset #
  210.         beq.s    nochgpres    ;zero = no preset
  211.         lea    prevmidicpres(pc),a1
  212.         cmp.b    0(a1,d1.w),d2    ;is this previous preset ??
  213.         beq.s    nochgpres    ;yes...no need to change
  214.         move.b    d2,0(a1,d1.w)    ;save preset to prevmidicpres
  215.         subq.b    #1,d2        ;sub 1 to get 0 - 127
  216.         lea    preschgdata(pc),a0
  217.         move.b    #$c0,(a0)    ;command: $C
  218.         or.b    d1,(a0)        ;"or" midi channel
  219.         move.b    d2,1(a0)    ;push the number to second byte
  220.         moveq    #5,d0        ;Noteondata follows preschgdata
  221.         bra.s    preschanged    ;struct, so this is a bit faster
  222. nochgpres:    moveq    #3,d0
  223. preschanged:    bsr.w    _AddMIDIData
  224.         bra.s    retsn2
  225.     ENDC
  226.  
  227.     IFNE    SYNTH
  228. handleSynthnote:
  229.         move.b    d1,trk_prevnote2(a5)
  230.         move.l    a0,trk_synthptr(a5)
  231.         cmp.w    #-2,4(a0)    ;HYBRID??
  232.         bne.s    hSn_nossn
  233.         st    trk_synthtype(a5)
  234.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  235.         bra.w    tlwtst0        ;go and play it
  236. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  237.         lea    _synthper(pc),a1
  238.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  239.         add.w    d1,d1
  240.         move.w    0(a1,d1.w),d1
  241.         movea.l    trk_audioaddr(a5),a1
  242.         move.b    trk_prevvol(a5),trk_synvol(a5)
  243.         move.w    d1,trk_prevper(a5)
  244.         move.w    d1,ac_per(a1)
  245.         clr.l    trk_sampleptr(a5)
  246. hSn2:        lea    trk_arpgoffs(a5),a1 ;clear synth-variables for new note
  247.         clr.l    (a1)+
  248.         clr.l    (a1)+
  249.         clr.l    (a1)+
  250.         clr.l    (a1)+
  251.         clr.b    (a1)+
  252.         addq.l    #1,a1    ;skip trk_prevnote2
  253.         movea.l    trk_synthptr(a5),a0
  254.         move.w    18(a0),(a1)+    ;trk_initvolxspd/trk_initwfxspd
  255.         clr.l    (a1)+
  256.         clr.w    (a1)
  257.         bsr.s    synth_start
  258.         bra.w    retsn2
  259.  
  260. synth_start:    move.l    a3,-(sp)
  261.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  262.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  263.         bgt.w    synth_wftbl        ;not 0...go to waveform
  264.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  265.         move.b    trk_volchgspd(a5),d0    ;volume change??
  266.         beq.s    synth_nochgvol        ;no.
  267.         add.b    trk_synvol(a5),d0    ;add previous volume
  268.         bpl.s    synth_voln2l        ;not negative
  269.         moveq    #0,d0            ;was negative => 0
  270. synth_voln2l:    cmp.b    #$40,d0            ;too high??
  271.         ble.s    synth_voln2h        ;not 2 high.
  272.         moveq    #$40,d0            ;was 2 high => 64
  273. synth_voln2h:    move.b    d0,trk_synvol(a5)    ;remember new...
  274.         move.b    d0,ac_vol+1(a3)        ;and change it
  275. synth_nochgvol:    move.w    trk_volcmd(a5),d0    ;get table position ptr
  276.         tst.b    trk_volwait(a5)        ;WAI(t) active
  277.         beq.s    synth_getvolcmd        ;no
  278.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  279.         ble.s    synth_getvolcmd        ;0 => continue
  280.         bra.w    synth_wftbl        ;> 0 => still wait
  281. synth_inccnt:    addq.b    #1,d0
  282. synth_getvolcmd:
  283.         addq.b    #1,d0            ;advance pointer
  284.         move.b    21(a0,d0.w),d1        ;get command
  285.         bmi.s    synth_cmd        ;negative = command
  286.         move.b    d1,trk_synvol(a5)    ;set synthvol
  287.         move.b    d1,ac_vol+1(a3)        ;change it!!
  288.         bra.s    synth_endvol        ;end of volume executing
  289. synth_cmd:    and.w    #$000f,d1
  290.         add.b    d1,d1
  291.         move.w    synth_vtbl(pc,d1.w),d1
  292.         jmp    syv(pc,d1.w)
  293. synth_vtbl:    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  294.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  295.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  296.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  297.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  298. syv:
  299. syv_fe:        move.b    22(a0,d0.w),d0        ;JMP
  300.         bra.s    synth_getvolcmd
  301. syv_f0:        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  302.         bra.s    synth_inccnt
  303. syv_f1:        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  304.         addq.b    #1,d0
  305.         bra.s    synth_endvol
  306. syv_f3:        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  307.         bra.s    synth_inccnt
  308. syv_f2:        move.b    22(a0,d0.w),d1
  309.         neg.b    d1
  310.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  311.         bra.s    synth_inccnt
  312. syv_fa:        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  313.         clr.b    trk_wfwait(a5)
  314.         bra.s    synth_inccnt
  315. syv_ff:        subq.b    #1,d0
  316. synth_endvol:    move.w    d0,trk_volcmd(a5)
  317. synth_wftbl:    move.b    trk_synvol(a5),trk_prevvol(a5)
  318.         adda.w    #158,a0
  319.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  320.         bgt.w    synth_arpeggio        ;not yet...
  321.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  322.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  323.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  324.         beq.s    synth_tstwfwai        ;0 = no change
  325. wytanwet:    add.w    trk_perchg(a5),d1    ;add value to current change
  326.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  327.         add.w    trk_prevper(a5),d1    ;add initial period to it
  328.         cmp.w    #113,d1            ;overflow??
  329.         bge.s    synth_pern2h
  330.         moveq    #113,d1
  331. synth_pern2h:    move.w    d1,ac_per(a3)        ;push the changed period
  332. synth_tstwfwai:    tst.b    trk_wfwait(a5)        ;WAI ??
  333.         beq.s    synth_getwfcmd        ;not waiting...
  334.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  335.         beq.s    synth_getwfcmd        ;waiting finished
  336.         bra.w    synth_arpeggio        ;still sleep...
  337. synth_incwfc:    addq.b    #1,d0
  338. synth_getwfcmd:    addq.b    #1,d0            ;advance position counter
  339.         move.b    -9(a0,d0.w),d1        ;get command
  340.         bmi.s    synth_wfcmd        ;negative = command
  341.         ext.w    d1            ;was positive->change wform
  342.         lsl.w    #2,d1            ;create index...
  343.         movea.l    120(a0,d1.w),a1        ;get wf address
  344.         addq.l    #2,a1            ;forget length-word
  345.         move.l    a1,ac_ptr(a3)        ;push new pointer
  346.         move.w    -(a1),ac_len(a3)    ;and the waveform length
  347.         bra.w    synth_wfend        ;no new commands now...
  348. synth_wfcmd:    and.w    #$000f,d1        ;get the right nibble
  349.         add.b    d1,d1            ;* 2
  350.         move.w    synth_wfctbl(pc,d1.w),d1
  351.         jmp    syw(pc,d1.w)        ;jump to command
  352. synth_wfctbl:    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  353.         dc.w    syw_f5-syw,syw_f6-syw,synth_wfend-syw,synth_wfend-syw
  354.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  355.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  356. syw:
  357. syw_fe:        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  358.         bra.s    synth_getwfcmd
  359. syw_fc:        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  360.         move.w    d0,trk_arpgoffs(a5)
  361. synth_findare:    addq.b    #1,d0
  362.         tst.b    -9(a0,d0.w)
  363.         bpl.s    synth_findare
  364.         bra.s    synth_getwfcmd
  365. syw_f0:        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  366.         bra    synth_incwfc
  367. syw_f1:        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  368.         addq.b    #1,d0
  369.         bra.s    synth_wfend
  370. syw_f4:        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  371.         bra.w    synth_incwfc
  372. syw_f5:        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  373.         addq.b    #1,trk_synthvibspd+1(a5)
  374.         bra.w    synth_incwfc
  375. syw_f2:        moveq    #0,d1            ;set slide down
  376.         move.b    -8(a0,d0.w),d1
  377. synth_setsld:    move.w    d1,trk_wfchgspd(a5)
  378.         bra.w    synth_incwfc
  379. syw_f3:        move.b    -8(a0,d0.w),d1        ;set slide up
  380.         neg.b    d1
  381.         ext.w    d1
  382.         bra.s    synth_setsld
  383. syw_f6:        clr.w    trk_perchg(a5)        ;reset period
  384.         move.w    trk_prevper(a5),ac_per(a3)
  385.         bra.w    synth_getwfcmd
  386. syw_fa:        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  387.         clr.b    trk_volwait(a5)
  388.         bra.w    synth_incwfc
  389. syw_ff:        subq.b    #1,d0        ;pointer = END - 1
  390. synth_wfend:    move.w    d0,trk_wfcmd(a5)
  391. synth_arpeggio:    move.w    trk_arpgoffs(a5),d0
  392.         beq.s    synth_vibrato
  393.         moveq    #0,d1
  394.         move.b    -8(a0,d0.w),d1
  395.         add.b    trk_prevnote2(a5),d1
  396.         movea.l    trk_periodtbl(a5),a1    ;get period table
  397.         add.w    d1,d1
  398.         move.w    0(a1,d1.w),d1
  399.         add.w    trk_perchg(a5),d1
  400.         move.w    d1,trk_prevper(a5)
  401.         move.w    d1,ac_per(a3)
  402.         addq.b    #1,d0
  403.         tst.b    -8(a0,d0.w)
  404.         bpl.s    synth_noarpres
  405.         move.w    trk_arpsoffs(a5),d0
  406. synth_noarpres:    move.w    d0,trk_arpgoffs(a5)
  407. synth_vibrato:    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  408.         beq.s    synth_rts        ;0 => no vibrato
  409.         move.w    trk_synviboffs(a5),d0    ;get offset
  410.         lsr.w    #4,d0            ;/ 16
  411.         and.w    #$1f,d0            ;sinetable offset (0-31)
  412.         move.b    sinetable(pc,d0.w),d0    ;get byte
  413.         ext.w    d0            ;to word
  414.         muls    d1,d0            ;amplify (* depth)
  415.         asr.w    #8,d0            ;and divide by 64
  416.         move.w    trk_prevper(a5),d1    ;get the old period
  417.         add.w    d0,d1            ;add vibrato...
  418.         add.w    trk_perchg(a5),d1    ;and pitch change...
  419.         move.w    d1,ac_per(a3)        ;change.
  420.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  421.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  422. synth_rts:    move.l    (sp)+,a3
  423.         rts
  424.     ENDC
  425. sinetable:    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  426.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  427.         dc.b    -106,-90,-71,-49,-25,0
  428.  
  429. _Wait1line:    move.l    d0,-(sp)
  430.         moveq    #$79,d0
  431. wl0:        move.b    $dff007,d1
  432. wl1:        cmp.b    $dff007,d1
  433.         beq.s    wl1
  434.         dbf    d0,wl0
  435.         move.l    (sp)+,d0
  436.         rts
  437. pushnewvals:    movea.l    (a1)+,a5
  438.         lsr.b    #1,d0
  439.         bcc.s    rpnewv
  440.         move.l    trk_sampleptr(a5),d1
  441.         beq.s    rpnewv
  442.         movea.l    trk_audioaddr(a5),a0
  443.         move.l    d1,ac_ptr(a0)
  444.         move.w    trk_samplelen(a5),ac_len(a0)
  445. rpnewv:        rts
  446. _StartDMA:        ;This small routine turns on audio DMA
  447.         move.w    dmaonmsk(pc),d0    ;dmaonmsk contains the mask of
  448.         beq.s    rpnewv    ;the channels that must be turned on
  449.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  450.         bsr.s    _Wait1line
  451.         move.w    d0,$dff096    ;do that!!!
  452.         bsr.s    _Wait1line
  453.         lea    trackdataptrs(pc),a1
  454.         bsr.s    pushnewvals
  455.         bsr.s    pushnewvals
  456.         bsr.s    pushnewvals
  457.         bra.s    pushnewvals
  458.  
  459. dmaonmsk:    dc.w    0
  460.     IFNE    MIDI
  461. prevmidicpres:    dc.l    0,0,0,0 ; 16 bytes
  462. prevmidipbend:    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  463.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  464.     ENDC
  465. ; TRACK-data structures (see definitions at the end of this file)
  466. t03d:        ds.b    20
  467.         dc.l    $dff0a0
  468.         ds.b    50+20
  469.         dc.l    $dff0b0
  470.         ds.b    50+20
  471.         dc.l    $dff0c0
  472.         ds.b    50+20
  473.         dc.l    $dff0d0
  474.         ds.b    50
  475. t415d:        ds.b    4*T415SZ
  476. t815d:        ds.b    8*T415SZ    ;8 bytes * 12 tracks = 96 bytes
  477. trackdataptrs:    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  478.         dc.l    t415d,t415d+T415SZ,t415d+2*T415SZ,t415d+3*T415SZ
  479.         dc.l    t815d,t815d+T415SZ,t815d+2*T415SZ,t815d+3*T415SZ
  480.         dc.l    t815d+4*T415SZ,t815d+5*T415SZ,t815d+6*T415SZ
  481.         dc.l    t815d+7*T415SZ
  482. numtracks:    dc.w    0
  483. numlines:    dc.w    0
  484. _counter:    dc.b    0
  485. nextblock:    dc.b    0
  486.  
  487. _IntHandler:    movem.l    d2-d7/a2-a5,-(sp)
  488.         movea.l    _module(pc),a6    ;a6 = pointer of MMD0
  489.         move.l    a6,d0
  490.         beq.w    plr_exit
  491.         clr.w    dmaonmsk
  492.         movea.l    8(a6),a4    ;a4 = pointer of MMD0song
  493.         moveq    #0,d3
  494.         lea    _counter(pc),a0
  495.         move.b    (a0),d3
  496.         addq.b    #1,d3
  497.         cmp.b    769(a4),d3
  498.         bge.s    plr_pnewnote    ;play new note
  499.         move.b    d3,(a0)
  500.         bra.w    nonewnote    ;do just fx
  501. ; --- new note!! first get address of current block
  502. plr_pnewnote:    clr.b    (a0)        ;clear counter
  503. ; --- now start to play it
  504.         move.w    pblock(pc),d0
  505.         movea.l    16(a6),a0
  506.         lsl.w    #2,d0
  507.         movea.l    0(a0,d0.w),a2    ;block...
  508.         move.b    (a2)+,numtracks+1
  509.         move.b    (a2)+,numlines+1
  510.         move.w    pline(pc),d0
  511.         move.w    d0,d1
  512.         add.w    d0,d0    ;d0 * 2
  513.         add.w    d1,d0    ;+ d0 = d0 * 3
  514.         mulu    numtracks(pc),d0
  515.         adda.w    d0,a2        ;a2 => pointer of curr. note
  516.         moveq    #0,d7        ;number of track
  517.         pea    trackdataptrs(pc)
  518. plr_loop0:    moveq    #0,d5
  519.         move.l    (sp),a1
  520.         movea.l    (a1)+,a5    ;get address of this track's struct
  521.         move.l    a1,(sp)
  522. ; ---------------- get the note numbers
  523.         move.b    (a2)+,d5    ;get the number of this note
  524.         move.b    (a2)+,d6    ;and the 4 numbers containing fx
  525.         move.b    (a2)+,trk_cmdqual(a5)    ;get & save the fx numbers
  526. ; ---------------- clear some instrument # flags
  527.         moveq    #0,d4        ;d4 is a flag: if set, instr. is
  528.         moveq    #0,d3        ;in range G-V. If clr, it's 1-F.
  529. ; ---------------- and set them, if needed
  530.         bclr    #7,d5        ;d3 is also a flag. If it's set,
  531.         sne    d4        ;the instr. is in range 10 - 1V
  532.         bclr    #6,d5
  533.         sne    d3
  534. ; ---------------- check if there's an instrument number
  535.         move.b    d6,d0
  536.         and.w    #$f0,d0        ;d0 now contains only the # of instr
  537.         bne.s    instnum        ;instrument number is not 0
  538.         tst.b    d4        ;maybe it's G (instr. #0, d4 set)
  539.         bne.s    instnum        ;yes, it really was G!!
  540.         tst.b    d3
  541.         beq.s    noinstnum    ;it wasn't 10 - 1V either..
  542. ; ---------------- if there was, GET IT!!
  543. instnum:    lsr.b    #4,d0        ;shift it right to get number 0-F
  544.         tst.b    d4
  545.         beq.s    nogtov2
  546.         add.w    #16,d0        ;if G-V, add 16 to the number
  547. nogtov2:    tst.b    d3
  548.         beq.s    no10to1v
  549.         add.w    #32,d0
  550. ; ---------------- finally, save the number
  551. no10to1v:    subq.b    #1,d0
  552.         move.b    d0,trk_previnstr(a5) ;remember instr. number!
  553. ; ---------------- remember hold/decay values
  554.         lea    holdvals(pc),a0
  555.         move.b    0(a0,d0.w),trk_inithold(a5)
  556.         move.b    63(a0,d0.w),trk_initdecay(a5)
  557. ; ---------------- get the pointer of data's of this sample in Song-struct
  558.         lsl.w    #3,d0        ;* 8
  559.         lea    0(a4,d0.w),a3    ;a3 contains now address of it
  560.         move.l    a3,trk_previnstra(a5)
  561.         moveq    #0,d0
  562. ; ---------------- get volume and make it relative (0 - 100 %)
  563.     IFNE    RELVOL
  564.         move.b    6(a3),d0
  565.         mulu    trk_trackvol(a5),d0
  566.         lsr.w    #8,d0
  567.         move.b    d0,trk_prevvol(a5) ;vol of this instr
  568.     ELSEIF
  569.         move.b    6(a3),trk_prevvol(a5)
  570.     ENDC
  571. ; ---------------- remember transpose
  572.         move.b    7(a3),trk_stransp(a5)
  573. ; ---------------- check the commands
  574. noinstnum:    move.b    d6,d0        ;effect again...
  575.         and.b    #$0f,d0        ;now check only the effect part
  576.         move.b    d0,trk_cmd(a5)    ;save the effect number
  577.         beq.w    plr_nocmd    ;no effect
  578.         move.b    trk_cmdqual(a5),d6    ;get qualifier...
  579. ; ---------------- there was a command (effect), but which one??
  580.         cmp.b    #$0f,d0        ;yes effect...is it Tempo???
  581.         bne.w    not0f        ;not Tempo
  582. ; ---------------- it was tempo (F)
  583.         tst.b    d6        ;test effect qual..
  584.         beq.s    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  585.         cmp.b    #$f0,d6        ;..is zero, go to next block
  586.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  587. ; ---------------- just an ordinary "change tempo"-request
  588.     IFNE    CIAB
  589.         moveq    #0,d0        ;will happen!!!
  590.         move.b    d6,d0
  591.         bsr    _SetTempo    ;change The Tempo
  592.     ENDC
  593.         bra.w    plr_nocmd
  594. ; ---------------- no, it was FFx, something special will happen!!
  595. fx0fspecial:    cmp.b    #$f2,d6    ; | rest - play | SpecialFX#2: no note..yet
  596.         bne.s    isfxfe    ;not SpecFX2
  597. ; ---------------- it was FF2, nothing to do now
  598.         move.b    d5,(a5)    ;Yes!!! Save the note number
  599.         moveq    #0,d5    ; clear the number for awhile
  600.         bra.w    plr_nocmd
  601. isfxfe:        cmp.b    #$fe,d6
  602.         bne.s    notcmdfe
  603. ; ---------------- it was FFE, stop playing
  604.         clr.w    pstate
  605.     IFNE    CIAB
  606.         movea.l    craddr(pc),a0
  607.         bclr    #0,(a0)        ;stop timer
  608.     ENDC
  609.         bsr.w    SoundOff
  610.         addq.l    #4,sp        ;trackdataptrs...
  611.         bra.w    plr_exit
  612. notcmdfe:    cmp.b    #$fd,d6 ;change period
  613.         bne.s    isfxff
  614. ; ---------------- FFD, change the period, don't replay the note
  615.     IFNE    CHECK
  616.         cmp.w    #4,d7 ;no tracks 4 - 15, thank you!!
  617.         bge.w    plr_nocmd
  618.     ENDC
  619.         movea.l    trk_periodtbl(a5),a0    ;period table
  620.         subq.b    #1,d5    ;sub 1 to make "real" note number
  621.         bmi.w    plr_endloop0    ;under zero, do nothing
  622.         add.b    d5,d5
  623.         move.w    0(a0,d5.w),d0 ;get the period
  624.         movea.l    trk_audioaddr(a5),a0
  625.         move.w    d0,ac_per(a0) ;push the period
  626.         moveq    #0,d5 ;and clear it so that it won't be replayed
  627.         bra.w    plr_nocmd    ;done!!
  628. isfxff:        cmp.b    #$ff,d6        ;note off??
  629.         bne.w    plr_nocmd
  630.         move.w    d7,d0
  631.         bsr.w    _ChannelOff
  632.         bra.w    plr_nocmd
  633. ; ---------------- F00, called Pattern Break in ST
  634. fx0fchgblck:    addq.b    #1,nextblock    ;next block????...YES!!!! (F00)
  635.         bra.w    plr_nocmd
  636. ; ---------------- was not Fxx, then it's something else!!
  637. not0f:        cmp.b    #$0e,d0
  638.         bne.s    not0e
  639.         move.b    d6,trk_wfcmd+1(a5) ;set waveform command position ptr
  640.         bra.w    plr_nocmd
  641. not0e:        cmp.b    #$0c,d0        ;new volume???
  642.         bne.s    not0c        ;NO!!!!!!!!!!!!!!!!!!!!!!
  643. ; ---------------- change volume
  644.         move.b    d6,d0
  645.         btst    #4,767(a4)    ;look at flags
  646.         bne.s    volhex
  647.         lsr.b    #4,d0        ;get number from left
  648.         mulu    #10,d0        ;number of tens
  649.         move.b    d6,d1        ;get again
  650.         and.b    #$0f,d1        ;this time don't get tens
  651.         add.b    d1,d0        ;add them
  652. volhex:
  653.     IFNE    CHECK
  654.         cmp.b    #64,d0
  655.         bls.s    novolov64
  656.         moveq    #64,d0
  657.     ENDC
  658. novolov64:
  659.     IFNE    RELVOL
  660.         mulu    trk_trackvol(a5),d0
  661.         lsr.w    #8,d0
  662.     ENDC
  663.         move.b    d0,trk_prevvol(a5)
  664.         bra.s    plr_nocmd
  665. ; ---------------- tempo2 change??
  666. not0c:        cmp.b    #$09,d0
  667.         bne.s    not09
  668.     IFNE    CHECK
  669.         and.b    #$1F,d6
  670.         bne.s    fx9chk
  671.         moveq    #$20,d6
  672.     ENDC
  673. fx9chk:        move.b    d6,769(a4)
  674.         bra.s    plr_nocmd
  675. ; ---------------- note off time set??
  676. not09:        cmp.b    #$08,d0
  677.         bne.s    not08
  678.         move.b    d6,d0
  679.         lsr.b    #4,d6        ;extract left  nibble
  680.         and.b    #$0f,d0        ; "   "  right  "  "
  681.         move.b    d6,trk_initdecay(a5)    ;left = decay
  682.         move.b    d0,trk_inithold(a5)    ;right = hold
  683.         bra.s    plr_nocmd
  684. ; ---------------- cmd Bxx, "position jump", like Goto, yäk!!
  685. not08:        cmp.b    #$0b,d0
  686.         bne.s    not0b
  687.         move.w    d6,d0
  688.         and.w    #$00ff,d0
  689.     IFNE    CHECK
  690.         cmp.w    506(a4),d0    ;test the song length
  691.         bhi.s    plr_nocmd
  692.     ENDC
  693.         move.w    d0,pseq
  694.         st    nextblock    ; = 1
  695.         bra.s    plr_nocmd
  696. ; ---------------- try portamento (3)
  697. not0b:        cmp.b    #$03,d0
  698.         bne.s    plr_nocmd
  699.         subq.b    #1,d5        ;subtract note number
  700.         bpl.s    plr_fx3note    ;there's a note...
  701.         tst.b    d6        ;qual??
  702.         beq.s    plr_endloop0    ;0 -> do nothing
  703.         bra.s    plr_setfx3spd    ;not 0 -> set new speed
  704. plr_fx3note:
  705.     IFNE    CHECK
  706.         cmp.w    #4,d7
  707.         bge.s    plr_endloop0    ;hey, what are you trying to do??
  708.     ENDC
  709.         movea.l    trk_periodtbl(a5),a0
  710.         add.b    766(a4),d5    ;play transpose
  711.         add.b    trk_stransp(a5),d5 ;and instrument transpose
  712.         bmi.s    plr_endloop0    ;again.. too low
  713.         add.w    d5,d5
  714.         move.w    0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
  715. plr_setfx3spd:    move.b    d6,trk_prevportspd(a5)    ;remember size
  716.         moveq    #0,d5    ;don't play this one
  717. ; ---------------- everything is checked now: play or not to play??
  718. plr_nocmd:    tst.b    d5    ;Now we'll check if we have to play a note
  719.         beq.s    plr_endloop0    ;no.
  720. ; ---------------- we decided to play
  721.         move.b    d5,(a5)
  722.         move.w    d7,d0
  723.         move.w    d5,d1
  724.         moveq    #0,d2
  725.         move.b    trk_prevvol(a5),d2    ;get volume
  726.         moveq    #0,d3
  727.         move.b    trk_previnstr(a5),d3    ;instr #
  728.         movea.l    trk_previnstra(a5),a3    ;instr data address
  729. ; ---------------- does this instrument have holding??
  730.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  731.         bne.s    plr_holdok    ;not 0 -> OK
  732.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  733. ; ---------------- and finally:
  734. plr_holdok:    bsr    _PlayNote    ;play it!!!!!!!!!!!
  735. ; ---------------- end of loop: handle next track, or quit
  736. plr_endloop0:    addq.b    #1,d7
  737.         cmp.w    numtracks(pc),d7
  738.         blt.w    plr_loop0
  739.         addq.l    #4,sp        ;trackdataptrs
  740.  
  741. ; and advance song pointers
  742.         lea    pline(pc),a3
  743.         move.w    (a3),d1        ;pline
  744.         addq.w    #1,d1        ;very important!!! advance line!!
  745.         cmp.w    numlines(pc),d1    ;important too!!! advance block??
  746.         bgt.s    plr_chgblock    ;yes!!!
  747.         tst.b    nextblock    ;command F00 ??
  748.         beq.s    plr_nochgblock    ;no, don't change block
  749. plr_chgblock:    moveq    #0,d1        ;clear line number
  750.         cmp.w    #2,6(a3)    ;play block/play song?
  751.         bne.s    plr_nonewseq    ;play block only...
  752.         move.w    4(a3),d0    ;get play sequence number
  753.         tst.b    nextblock
  754.         bmi.s    plr_noadvseq    ;Bxx sets nextblock to 0xff (= neg)
  755.         addq.w    #1,d0        ;advance sequence number
  756. plr_noadvseq:    cmp.w    506(a4),d0    ;is this the highest seq number??
  757.         blt.s    plr_notagain    ;no.
  758.         moveq    #0,d0        ;yes: play song again
  759.         moveq    #0,d1            ;...forever!!!
  760. plr_notagain:    move.b    d0,5(a3)    ;remember new playseq-#
  761.         lea    508(a4),a0    ;offset in sequence table
  762.         move.b    0(a0,d0.w),d0    ;get number of the block
  763.     IFNE    CHECK
  764.         cmp.b    505(a4),d0    ;beyond last block??
  765.         blt.s    plr_nolstblk    ;no..
  766.         moveq    #0,d0        ;play block 0
  767.     ENDC
  768. plr_nolstblk:    move.b    d0,3(a3)    ;store pblock
  769. plr_nonewseq:    clr.b    nextblock    ;clear this if F00 set it
  770. plr_nochgblock:    move.w    d1,(a3)        ;set new pline
  771.         movea.l    16(a6),a0
  772.         move.w    2(a3),d0    ;pblock
  773.         lsl.w    #2,d0
  774.         movea.l    0(a0,d0.w),a2    ;block...
  775.         move.b    (a2),d7        ;# of tracks
  776.         move.w    (a3),d0        ;play line
  777.         move.w    d0,d1
  778.         add.w    d0,d0    ;d0 * 2
  779.         add.w    d1,d0    ;+ d0 = d0 * 3
  780.         mulu    d7,d0
  781.         lea    2(a2,d0.w),a2
  782.         move.b    769(a4),d3    ;interrupts/note
  783.         lea    trackdataptrs(pc),a0
  784.         subq.b    #1,d7
  785. plr_chkhold:    movea.l    (a0)+,a1    ;track data
  786.         tst.b    trk_noteoffcnt(a1)    ;hold??
  787.         bmi.s    plr_holdend    ;no.
  788.         move.b    (a2),d1        ;get the 1st byte..
  789.         bne.s    plr_hold1
  790.         move.b    1(a2),d1
  791.         and.b    #$f0,d1
  792.         beq.s    plr_holdend    ;don't hold
  793.         bra.s    plr_hold2
  794. plr_hold1:    and.b    #$3f,d1        ;note??
  795.         beq.s    plr_hold2    ;no, cont hold..
  796.         move.b    1(a2),d1
  797.         and.b    #$0f,d1        ;get cmd
  798.         subq.b    #3,d1        ;is there command 3 (slide)
  799.         bne.s    plr_holdend    ;no -> end holding
  800. plr_hold2:    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  801. plr_holdend:    addq.l    #3,a2        ;next note
  802.         dbf    d7,plr_chkhold
  803.         btst    #5,767(a4)    ;FLAG_STSLIDE??
  804.         bne.w    plr_endfx    ;yes, no effects this time...
  805.         moveq    #0,d3        ;counter = 0!!!
  806. nonewnote:
  807. ;    *********************** This code produces the effects **
  808.         moveq    #0,d7    ;clear track count
  809.         moveq    #0,d6
  810.         lea    trackdataptrs(pc),a2
  811. plr_loop1:    movea.l    (a2)+,a5
  812.         moveq    #0,d5
  813.         moveq    #0,d4
  814.         move.b    trk_cmd(a5),d6    ;get the fx number
  815.         move.b    trk_cmdqual(a5),d4    ;and the last 2 #'s
  816.     IFNE    MIDI
  817.         tst.b    trk_prevmidin(a5)    ;first: is it MIDI??
  818.         bne.w    midifx
  819.     ENDC
  820.         cmp.w    #4,d7
  821.         bge.w    endl    ;no non-MIDI effects in tracks 4 - 15
  822.         tst.b    trk_noteoffcnt(a5)
  823.         bmi.s    plr_nowaitoff
  824.         subq.b    #1,trk_noteoffcnt(a5)
  825.         bpl.s    plr_nowaitoff
  826.     IFNE    SYNTH
  827.         tst.b    trk_synthtype(a5)    ;synth/hybrid??
  828.         beq.s    plr_nosyndec
  829.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  830.         clr.b    trk_volwait(a5)    ;abort WAI
  831.         move.l    trk_synthptr(a5),d0
  832.         bra.s    plr_gosynth
  833.     ENDC
  834. plr_nosyndec:    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  835.         bne.s    plr_nowaitoff    ;if > 0, don't stop sound
  836.         bset    d7,d5
  837.         move.w    d5,$dff096    ;stop DMA...
  838.         moveq    #0,d5
  839. plr_nowaitoff:
  840.     IFNE    SYNTH
  841.         move.l    trk_synthptr(a5),d0
  842.         beq.s    plr_nosynth
  843. plr_gosynth:    move.l    d0,a0
  844.         bsr.w    synth_start
  845.     ENDC
  846. plr_nosynth:    move.b    trk_fadespd(a5),d0    ;fade??
  847.         beq.s    plr_nofade    ;no.
  848.         sub.b    d0,trk_prevvol(a5)
  849.         bpl.s    plr_nofade2low
  850.         clr.b    trk_prevvol(a5)
  851.         clr.b    trk_fadespd(a5)        ;fade no more
  852. plr_nofade2low:    movea.l    trk_audioaddr(a5),a1
  853.         move.b    trk_prevvol(a5),ac_vol+1(a1)
  854. plr_nofade:    add.b    d6,d6    ;* 2
  855.         move.w    fx_table(pc,d6.w),d0
  856.         jmp    fxs(pc,d0.w)
  857. fx_table:    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  858.         dc.w    fx_05-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  859.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
  860.         dc.w    fx_0f-fxs
  861. fxs:
  862. ;    **************************************** Effect 01 ******
  863. fx_01:        sub.w    d4,trk_prevper(a5)    ;slide it up!!!
  864.         move.w    trk_prevper(a5),d5
  865.         cmp.w    #113,d5        ;too high???
  866.         bge    newvals
  867.         move.w    #113,d5        ;yes, too high!!!
  868.         move.w    d5,trk_prevper(a5)
  869.         bra    newvals
  870. ;    **************************************** Effect 02 ******
  871. fx_02:        add.w    d4,trk_prevper(a5)    ;slide it down!!!!!!!!!
  872.         move.w    trk_prevper(a5),d5
  873.         bra.w    newvals
  874. ;    **************************************** Effect 00 ******
  875. fx_00:        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio!!
  876.         beq.w    endl
  877.         move.l    d3,d0
  878.         divu    #3,d0
  879.         swap    d0
  880.         tst.w    d0
  881.         bne.s    fx_arp12
  882.         and.b    #$0f,d4
  883.         add.b    (a5),d4
  884.         bra.s    fx_doarp
  885. fx_arp12:    subq.b    #1,d0
  886.         bne.s    fx_arp2
  887.         lsr.b    #4,d4
  888.         add.b    (a5),d4
  889.         bra.s    fx_doarp
  890. fx_arp2:    move.b    (a5),d4
  891. fx_doarp:    subq.b    #1,d4        ;-1 to make it 0 - 127
  892.         add.b    766(a4),d4    ;add play transpose
  893.         add.b    trk_stransp(a5),d4    ;add instrument transpose
  894.         lsl.b    #1,d4        ;shift to make index for UWORD
  895.         movea.l    trk_periodtbl(a5),a1
  896.         move.w    0(a1,d4.w),d5
  897.         bra.w    newvals
  898. ;    **************************************** Effect 0D/0A ***
  899. fx_0a:
  900. fx_0d:        move.b    d4,d1
  901.         move.b    trk_prevvol(a5),d0    ;move previous vol to d0
  902.         and.b    #$f0,d1
  903.         bne.s    crescendo
  904.         sub.b    d4,d0    ;sub from prev. vol
  905.         bpl.s    novolund0
  906.         moveq    #0,d0    ;volumes under zero not accepted!!!
  907. novolund0:    move.b    d0,trk_prevvol(a5)    ;put new vol back
  908.         move.b    d0,d1
  909.         bra    dispvolchng
  910. crescendo:    lsr.b    #4,d1
  911.         add.b    d1,d0
  912.         cmp.b    #64,d0
  913.         ble.s    novolover64
  914.         moveq    #64,d0
  915. novolover64:    move.b    d0,trk_prevvol(a5)
  916.         move.b    d0,d1
  917.         bra.w    dispvolchng
  918. ;    **************************************** Effect 05 ******
  919. fx_05:        move.w    trk_prevper(a5),d5 ;this is very simple: get the old period
  920.         cmp.b    #3,d3        ;and..
  921.         bge.w    newvals        ;if counter < 3
  922.         sub.w    d4,d5    ;subtract effect qualifier
  923.         bra.w    newvals
  924. ;    **************************************** Effect 03 ******
  925. fx_03:        move.w    trk_porttrgper(a5),d0    ;d0 = target period
  926.         beq.w    newvals    ;no target period specified
  927.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  928.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  929.         cmp.w    d0,d1
  930.         bhi.s    subper    ;curr. period > target period
  931.         add.w    d4,d1    ;add the period
  932.         cmp.w    d0,d1
  933.         bge.s    targreached
  934.         bra.s    targnreach
  935. subper:        sub.w    d4,d1    ;subtract
  936.         cmp.w    d0,d1    ;compare current period to target period
  937.         bhi.s    targnreach
  938. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  939.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  940. targnreach:    move.w    d1,trk_prevper(a5)
  941.         move.w    d1,d5
  942.         bra.w    newvals
  943. ;    *********************************************************
  944. fx_0c:        cmp.b    #1,d3
  945.         bne.w    newvals
  946.         move.b    trk_prevvol(a5),d1
  947. dispvolchng:    bra.w    newvals
  948. ;    **************************************** Effect 04 ******
  949. fx_04:        tst.b    d4
  950.         beq.s    nonvib
  951.         move.b    d4,trk_vibrspdsz(a5)
  952. nonvib:        move.b    trk_vibroffs(a5),d0
  953.         lsr.b    #2,d0
  954.         and.w    #$1f,d0
  955.         moveq    #0,d1
  956.         lea    sinetable(pc),a0
  957.         move.b    0(a0,d0.w),d5
  958.         ext.w    d5
  959.         move.b    trk_vibrspdsz(a5),d0
  960.         and.w    #$000f,d0
  961.         muls    d0,d5
  962.         asr.w    #5,d5
  963.         add.w    trk_prevper(a5),d5
  964.         move.b    trk_vibrspdsz(a5),d0
  965.         lsr.b    #3,d0
  966.         and.b    #$3e,d0
  967.         add.b    d0,trk_vibroffs(a5)
  968.         bra.s    newvals
  969. ;    **************************************** Effect 0F ******
  970. fx_0f:        cmp.b    #$f1,d4
  971.         bne.s    no0ff1
  972.         cmp.b    #3,d3
  973.         bne.w    endl
  974.         bra.s    playfxnote
  975. no0ff1:        cmp.b    #$f2,d4
  976.         bne.s    no0ff2
  977.         cmp.b    #3,d3
  978.         bne.w    endl
  979.         bra.s    playfxnote
  980. no0ff2:        cmp.b    #$f3,d4
  981.         bne.s    no0ff3
  982.         move.b    d3,d0
  983.         and.b    #2+4,d0        ;is 2 or 4
  984.         beq.w    endl
  985. playfxnote:    move.w    d7,d0        ;track # to d0...
  986.         moveq    #0,d1
  987.         move.b    (a5),d1        ;get note # of previous note
  988.         moveq    #0,d2
  989.         move.b    trk_prevvol(a5),d2    ;get previous volume
  990.         move.w    d3,-(sp)
  991.         moveq    #0,d3
  992.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  993.         movea.l    trk_previnstra(a5),a3
  994.         bsr    _PlayNote
  995.         move.w    (sp)+,d3
  996.         bra.s    endl
  997. no0ff3:        cmp.b    #$f8,d4        ;f8 = filter off
  998.         beq.s    plr_filteroff
  999.         cmp.b    #$f9,d4        ;f9 = filter on
  1000.         bne.s    endl
  1001.         bclr    #1,$bfe001
  1002.         bra.s    endl
  1003. plr_filteroff:    bset    #1,$bfe001
  1004.         bra.s    endl
  1005. ;    *********************************************************
  1006. newvals:    movea.l    trk_audioaddr(a5),a1    ;get channel address
  1007.         tst.w    d5    ;now: do the effects!!!
  1008.         beq.s    plr_oldper
  1009. plr_newper:    move.w    d5,ac_per(a1)    ;push period
  1010. plr_oldper:    move.b    trk_prevvol(a5),ac_vol+1(a1)    ;get volume & push it
  1011. fx_xx:
  1012. endl:        addq.b    #1,d7    ;increment channel number
  1013.         cmp.w    numtracks(pc),d7    ;all channels done???
  1014.         blt.w    plr_loop1    ;not yet!!!
  1015. plr_endfx:    bsr    _StartDMA    ;turn on DMA
  1016. plr_exit:    movem.l    (sp)+,d2-d7/a2-a5
  1017.         rts
  1018.  
  1019. pline:        dc.w    0
  1020. pblock:        dc.w    0
  1021. pseq:        dc.w    0
  1022. pstate:        dc.w    0
  1023.  
  1024. _SetTempo:
  1025.     IFNE    CIAB
  1026.         cmp.b    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  1027.         bhi.s    calctempo
  1028.         subq.b    #1,d0
  1029.         lsl.w    #1,d0
  1030.         move.w    sttempo+2(pc,d0.w),d1
  1031.         bra.s    pushtempo
  1032. calctempo:    move.l    timerdiv(pc),d1
  1033.         divu    d0,d1
  1034. pushtempo:    movea.l    craddr+4(pc),a0
  1035.         move.b    d1,(a0)        ;and set the CIA timer
  1036.         lsr.w    #8,d1
  1037.         movea.l    craddr+8(pc),a0
  1038.         move.b    d1,(a0)
  1039.     ENDC
  1040.         rts ;   vv-- These values are the SoundTracker tempos (approx.)
  1041. sttempo:    dc.w    $0f00
  1042.     IFNE    CIAB
  1043.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  1044. timerdiv:    dc.l    470000    ;this value for CIA freq 709 379 Hz (PAL..)
  1045.     ENDC
  1046.  
  1047.     IFNE    MIDI
  1048. midifx:        tst.b    trk_noteoffcnt(a5)
  1049.         bmi.s    midi_nowaitoff
  1050.         subq.b    #1,trk_noteoffcnt(a5)
  1051.         bpl.s    midi_nowaitoff
  1052.         move.l    a5,a1
  1053.         move.b    trk_prevmidin(a5),d1
  1054.         beq.s    midi_nowaitoff    ;no note
  1055.         bsr.w    choff_midi
  1056. midi_nowaitoff:    cmp.b    #1,d6
  1057.         bne.s    nomidi01fx
  1058.         lea    prevmidipbend(pc),a0
  1059.         moveq    #0,d1
  1060.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  1061.         lsl.w    #1,d1        ;UWORD index
  1062.         tst.b    d4        ;x100??
  1063.         beq.s    resetpbend
  1064.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  1065.         lsl.w    #3,d4        ;multiply bend value by 8
  1066.         add.w    d4,d0
  1067.         cmp.w    #$3fff,d0
  1068.         bls.s    bendpitch
  1069.         move.w    #$3fff,d0
  1070. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  1071.         lsr.b    #1,d1        ;back to UBYTE
  1072.         or.b    #$e0,d1
  1073.         lea    noteondata(pc),a0
  1074.         move.b    d1,(a0)        ;midi command & channel
  1075.         move.b    d0,1(a0)    ;lower value
  1076.         and.b    #$7f,1(a0)    ;clear bit 7
  1077.         lsr.w    #7,d0
  1078.         and.b    #$7f,d0        ;clr bit 7
  1079.         move.b    d0,2(a0)    ;higher 7 bits
  1080.         moveq    #3,d0
  1081.         bsr.w    _AddMIDIData
  1082.         bra.w    endl
  1083. nomidi01fx:    cmp.b    #2,d6
  1084.         bne.s    nomidi02fx
  1085.         lea    prevmidipbend(pc),a0
  1086.         moveq    #0,d1
  1087.         move.b    trk_prevmidich(a5),d1
  1088.         lsl.w    #1,d1
  1089.         tst.b    d4
  1090.         beq.s    resetpbend    ;x200??
  1091.         move.w    0(a0,d1.w),d0
  1092.         lsl.w    #3,d4
  1093.         sub.w    d4,d0
  1094.         bpl.s    bendpitch    ;not under 0
  1095.         moveq    #0,d0
  1096.         bra.s    bendpitch
  1097. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  1098.         bne.w    endl
  1099.         move.w    #$2000,d0
  1100.         bra.s    bendpitch
  1101. nomidi02fx:    cmp.b    #$04,d6
  1102.         bne.s    nomidi04fx
  1103.         moveq    #$01,d0
  1104.         bra.s    pushctrldata
  1105. nomidi04fx:    cmp.b    #$0e,d6        ;with MIDI, this is "pan", when
  1106.         bne.s    nomidi0efx    ;values are 0 - $7f
  1107.         moveq    #$0a,d0
  1108. pushctrldata:    tst.b    d3        ;do it only once in a note
  1109.         bne.w    endl        ;(when counter = 0)
  1110.         lea    noteondata(pc),a0 ;push "control change" data,
  1111.         move.b    trk_prevmidich(a5),(a0)      ;d0 = 1. databyte, d4 = 2. db
  1112.         or.b    #$b0,(a0)
  1113.         move.b    d0,1(a0)
  1114.         move.b    d4,2(a0)
  1115.         bmi.w    endl    ;I said 0 - $7f!!! (for future compatibility)
  1116.         moveq    #3,d0
  1117.         bsr.w    _AddMIDIData
  1118.         bra.w    endl
  1119. nomidi0efx:    cmp.b    #$0f,d6
  1120.         bne.w    endl
  1121.         cmp.b    #$fa,d4        ;hold pedal ON
  1122.         bne.s    nomffa
  1123.         moveq    #$40,d0
  1124.         moveq    #$7f,d4
  1125.         bra.s    pushctrldata
  1126. nomffa:        cmp.b    #$fb,d4        ;hold pedal OFF
  1127.         bne.s    nomffb
  1128.         moveq    #$40,d0
  1129.         moveq    #$00,d4
  1130.         bra.s    pushctrldata
  1131. nomffb:        bra.w    fx_0f
  1132.  
  1133. _ResetMIDI:    movem.l    d2/a2,-(sp)
  1134.         lea    prevmidicpres(pc),a0
  1135.         clr.l    (a0)+    ;force presets to be set again
  1136.         clr.l    (a0)+    ;(clear prev. preset numbers)
  1137.         clr.l    (a0)+
  1138.         clr.l    (a0)+
  1139.         clr.b    lastcmdbyte
  1140.         lea    midiresd(pc),a2
  1141.         move.b    #$e0,(a2)    ;reset pitchbenders & mod. wheel
  1142.         move.b    #$b0,3(a2)
  1143.         moveq    #15,d2
  1144. respbendl:    movea.l    a2,a0
  1145.         moveq    #6,d0
  1146.         bsr.w    _AddMIDIData
  1147.         addq.b    #1,(a2)
  1148.         addq.b    #1,3(a2)
  1149.         dbf    d2,respbendl
  1150.         lea    prevmidipbend(pc),a2
  1151.         moveq    #15,d2
  1152. resprevpbends:    move.w    #$2000,(a2)+
  1153.         dbf    d2,resprevpbends
  1154.         movem.l    (sp)+,d2/a2
  1155.         rts
  1156. midiresd:    dc.b    $e0,$00,$40,$b0,$01,$00
  1157.     ENDC
  1158.  
  1159. getinsdata:    moveq    #0,d2
  1160.     IFNE    IFF53
  1161.         move.w    4(a0),d0    ;Soitin-struct in a0
  1162.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  1163.     ENDC
  1164.         move.l    a0,d0
  1165.         lea    _periods(pc),a0
  1166.         move.l    a0,trk_periodtbl(a5)
  1167.         lsl.b    #1,d1
  1168.         move.w    0(a0,d1.w),d5 ;put period to d5
  1169.         move.l    d0,a0
  1170.         addq.l    #6,d0        ;Skip structure
  1171.         move.l    (a0),d1        ;length
  1172.         move.w    (a3),d2
  1173.         move.w    2(a3),d3
  1174.         rts
  1175.     IFNE    IFF53
  1176. iff5or3oct:    movem.l    d6-d7,-(sp)
  1177.         moveq    #0,d7
  1178.         move.w    d1,d7
  1179.         divu    #12,d7    ;octave #
  1180.         move.l    d7,d5
  1181.         swap    d5    ;note number in this oct (0-11) is in d5
  1182.         move.l    (a0),d1
  1183.         cmp.b    #2,d0
  1184.         bne.s    no3oct
  1185.         addq.l    #6,d7
  1186.         divu    #7,d1    ;get length of the 1st octave
  1187.         bra.s    no5oct
  1188. no3oct:        divu    #31,d1    ;get length of the 1st octave (5 octaves)
  1189. no5oct:        move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  1190.         move.w    (a3),d2
  1191.         move.w    2(a3),d3
  1192.         moveq    #0,d6
  1193.         move.b    shiftcnt(pc,d7.w),d6
  1194.         lsl.w    d6,d2
  1195.         lsl.w    d6,d3
  1196.         lsl.w    d6,d1
  1197.         move.b    mullencnt(pc,d7.w),d6
  1198.         mulu    d6,d0        ;offset of this oct from 1st oct
  1199.         add.l    a0,d0        ;add base address to offset
  1200.         addq.l    #6,d0        ;skip structure
  1201.         lea    _periods(pc),a1
  1202.         add.b    octstart(pc,d7.w),d5
  1203.         lsl.b    #1,d5
  1204.         move.w    0(a1,d5.w),d5
  1205.         movem.l    (sp)+,d6-d7
  1206.         rts    ;returns period in d5
  1207. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0
  1208. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0
  1209. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36
  1210.     ENDC
  1211.  
  1212.     xdef    _startmusic
  1213.     xdef    _endmusic
  1214.  
  1215. relocentr:
  1216.     tst.l   (a0)
  1217.     beq.s   norel
  1218.     add.l   d1,(a0)
  1219. norel:    addq.l  #4,a0
  1220.     rts
  1221. _RelocModule:
  1222.     movem.l    a2-a3/d2-d3,-(sp)
  1223.     movea.l a0,a2
  1224.     move.l  a2,d1        ;d1 = ptr to start of module
  1225.     lea     8(a2),a0
  1226.     bsr.s   relocentr    ;reloc song ptr
  1227.     addq.l  #4,a0
  1228.     bsr.s   relocentr    ;reloc blockarr ptr
  1229.     addq.l  #4,a0
  1230.     bsr.s   relocentr    ;reloc smplarr ptr
  1231.     addq.l  #4,a0
  1232.     bsr.s   relocentr    ;reloc expdata ptr
  1233.     movea.l 24(a2),a0
  1234.     movea.l 8(a2),a1
  1235.     moveq   #0,d0
  1236.     move.b  787(a1),d0    ;number of samples
  1237.     subq.b  #1,d0
  1238. relocs:    bsr.s   relocentr
  1239.     move.l    -4(a0),d3    ;sample ptr
  1240.     beq.s    nosyn
  1241.     move.l    d3,a3
  1242.     tst.w    4(a3)
  1243.     bpl.s    nosyn        ;type >= 0
  1244.     move.w    20(a3),d2    ;number of waveforms
  1245.     lea    278(a3),a3    ;ptr to wf ptrs
  1246.     subq.w    #1,d2
  1247. relsyn:    add.l    d3,(a3)+
  1248.     dbf    d2,relsyn
  1249. nosyn:    dbf     d0,relocs
  1250.     movea.l 16(a2),a0
  1251.     move.w  504(a1),d0
  1252.     subq.b  #1,d0
  1253. relocb:    bsr.s   relocentr
  1254.     dbf     d0,relocb
  1255.     move.l    32(a2),d0    ;extension struct
  1256.     beq.s    rel_ex
  1257.     move.l    d0,a0
  1258.     addq.l    #4,a0        ;pass "reserved"
  1259.     bsr.s    relocentr    ;InstrExt...
  1260.     addq.l    #4,a0        ;pass sizes of InstrExt
  1261.     bsr.s    relocentr    ;annotxt
  1262. rel_ex    movem.l    (sp)+,d2-d3/a2-a3
  1263.     rts
  1264.  
  1265. _InitModule:    movem.l    a2-a3/d2,-(sp)
  1266.         move.l    a0,d0
  1267.         beq.s    IM_exit        ;0 => xit
  1268.     IFNE    RELVOL
  1269.         movea.l    8(a0),a1    ;MMD0song
  1270.         move.b    786(a1),d0    ;d0 = mastervol
  1271.         ext.w    d0
  1272.         lea    770(a1),a1    ;a1 = trkvol
  1273.         lea    trackdataptrs(pc),a2
  1274.         moveq    #15,d1
  1275. IM_loop0    move.b    (a1)+,d2    ;get vol...
  1276.         ext.w    d2
  1277.         move.l    (a2)+,a3    ;pointer to track data
  1278.         mulu    d0,d2        ;mastervol * trackvol
  1279.         lsr.w    #4,d2
  1280.         move.w    d2,trk_trackvol(a3)
  1281.         dbf    d1,IM_loop0
  1282.     ENDC
  1283.         lea    holdvals(pc),a2
  1284.         move.l    32(a0),d0    ;expdata...
  1285.         beq.s    IM_clrhlddec    ;none here
  1286.         move.l    d0,a1
  1287.         move.l    4(a1),d0    ;exp_smp
  1288.         beq.s    IM_clrhlddec    ;again.. nothing
  1289.         move.l    d0,a0        ;InstrExt...
  1290.         move.w    8(a1),d2    ;# of entries
  1291.         beq.s    IM_clrhlddec
  1292.         subq.w    #1,d2        ;- 1 (for dbf)
  1293.         move.w    10(a1),d0    ;entry size
  1294. IM_loop1    move.b    1(a0),63(a2)    ;InstrExt.decay ->decay
  1295.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  1296.         adda.w    d0,a0        ;ptr to next InstrExt
  1297.         dbf    d2,IM_loop1
  1298.         bra.s    IM_exit
  1299. IM_clrhlddec    moveq    #62,d0        ;no InstrExt => clear holdvals/decays
  1300. IM_loop2    clr.w    (a2)+
  1301.         dbf    d0,IM_loop2
  1302. IM_exit        movem.l    (sp)+,a2-a3/d2
  1303.         rts
  1304.  
  1305. _startmusic:
  1306.     IFNE    MIDI
  1307.         bsr.w    _GetSerial
  1308.         tst.l    d0
  1309.         bne.s    IP_error
  1310.     ENDC
  1311.         bsr.w    _AudioInit
  1312.         tst.l    d0
  1313.         bne.s    IP_error
  1314.         moveq    #33,d0
  1315.         bsr.w    _SetTempo    ;set default tempo
  1316.         lea    _playmodule,a0
  1317.         bsr.w    _RelocModule
  1318.         lea    _playmodule,a0
  1319.         bra.s    _PlayModule
  1320. IP_error    bsr.w    _endmusic
  1321.         moveq    #-1,d0
  1322.         rts
  1323.  
  1324. _endmusic:    move.b    _timeropen(pc),d0
  1325.         beq.s    RP_notimer    ;timer is not ours
  1326.         bsr.s    _StopPlayer
  1327. RP_notimer:    bsr.w    _AudioRem
  1328.     IFNE    MIDI
  1329.         bsr.w    _FreeSerial
  1330.     ENDC
  1331.         rts
  1332.  
  1333. _PlayModule:    move.l    a0,-(sp)
  1334.         bsr    _InitModule
  1335.         move.l    (sp)+,a0
  1336.         move.b    _timeropen(pc),d0
  1337.         beq.s    PM_end        ;resource allocation failure
  1338.         move.l    a0,d0
  1339.         beq.s    PM_end        ;module failure
  1340.     IFNE    CIAB
  1341.         movea.l    craddr(pc),a1
  1342.         bclr    #0,(a1)        ;stop timer...
  1343.     ENDC
  1344.         clr.l    _module
  1345.     IFNE    MIDI
  1346.         clr.b    lastcmdbyte
  1347.     ENDC
  1348.         move.l    a0,-(sp)
  1349.         movea.l    8(a0),a0    ;song
  1350.         move.b    769(a0),_counter    ;init counter
  1351.         btst    #0,767(a0)
  1352.         bne.s    PM_filon
  1353.         bset    #1,$bfe001
  1354.         bra.s    PM_filset
  1355. PM_filon    bclr    #1,$bfe001
  1356. PM_filset    move.w    764(a0),d0    ;get default tempo
  1357.         moveq    #0,d1
  1358.         move.b    508(a0),d1    ;get first playseq entry
  1359.         lea    pline(pc),a0    ;clear pline etc..
  1360.         move.l    d1,(a0)+
  1361.         moveq    #2,d1
  1362.         move.l    d1,(a0)        ;pstate = 2 (play song)
  1363.         move.l    (sp)+,_module
  1364.     IFNE    CIAB
  1365.         bsr.w    _SetTempo    ;set default tempo
  1366.         bset    #0,(a1)        ;start timer => PLAY!!
  1367.     ENDC
  1368. PM_end        rts
  1369.  
  1370. _StopPlayer:    move.b    _timeropen(pc),d0
  1371.         beq.s    SP_end        ;res. alloc fail.
  1372.     IFNE    CIAB
  1373.         movea.l    craddr(pc),a0
  1374.         bclr    #0,(a0)        ;stop timer
  1375.     ENDC
  1376.         clr.w    pstate
  1377.     IFNE    MIDI
  1378.         clr.b    lastcmdbyte
  1379.     ENDC
  1380.         bsr.w    SoundOff
  1381. SP_end        rts
  1382. ; *************************************************************************
  1383.  
  1384.  
  1385. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  1386.         moveq    #0,d2
  1387.         movea.l    4,a6
  1388. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  1389.     IFNE    AUDDEV
  1390.         addq.l    #1,d2
  1391.         moveq    #-1,d0
  1392.         jsr    -$14a(a6)    ;AllocSignal()
  1393.         tst.b    d0
  1394.         bmi.w    initerr
  1395.         move.b    d0,sigbitnum
  1396. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  1397.         lea    allocport(pc),a1
  1398.         move.b    d0,15(a1)    ;set mp_SigBit
  1399.         move.l    a1,-(sp)
  1400.         suba.l    a1,a1
  1401.         jsr    -$126(a6)    ;FindTask(0)
  1402.         move.l    (sp)+,a1
  1403.         move.l    d0,16(a1)    ;set mp_SigTask
  1404.         lea    reqlist(pc),a0
  1405.         move.l    a0,(a0)        ;NEWLIST begins...
  1406.         addq.l    #4,(a0)
  1407.         clr.l    4(a0)
  1408.         move.l    a0,8(a0)    ;NEWLIST ends...
  1409. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  1410.         addq.l    #1,d2
  1411.         lea    allocreq(pc),a1
  1412.         lea    audiodevname(pc),a0
  1413.         moveq    #0,d0
  1414.         moveq    #0,d1
  1415.         jsr    -$1bc(a6)    ;OpenDevice()
  1416.         tst.b    d0
  1417.         bne.w    initerr
  1418.         st.b    audiodevopen
  1419. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open ciaa.resource
  1420.         addq.l    #1,d2
  1421.     ENDC
  1422.     IFNE    CIAB
  1423.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  1424.         beq.s    init_pal
  1425.         move.l    #474326,timerdiv ;Assume that CIA freq is 715 909 Hz
  1426. init_pal:    moveq    #0,d0
  1427.         lea    ciabname(pc),a1
  1428.         jsr    -$1f2(a6)    ;OpenResource()
  1429.         tst.l    d0
  1430.         beq.s    initerr
  1431.         move.l    d0,_ciaresource
  1432. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  1433.         addq.l    #1,d2
  1434.         moveq    #2,d3
  1435.         lea    craddr(pc),a4
  1436.         move.l    #$bfdf00,(a4)+    ;Initialize Timer B addresses
  1437.         move.l    #$bfd600,(a4)+
  1438.         move.l    #$bfd700,(a4)
  1439.         move.l    d0,a6
  1440.         lea    timerinterrupt(pc),a1    ;Attempt to get timer B
  1441.         clr.l    -4(a1)            ;clear module pointer
  1442.         moveq    #1,d0    ;Bit number 1: Timer B
  1443.         jsr    -$6(a6)    ;AddICRVector
  1444.         tst.l    d0
  1445.         beq.s    gotTimerB        ;succeeded!!
  1446.         moveq    #1,d3
  1447.         lea    timerinterrupt(pc),a1    ;no. Get timer A then...
  1448.         moveq    #0,d0    ;Bit number 0: Timer A
  1449.         jsr    -$6(a6)
  1450.         tst.l    d0
  1451.         bne.s    initerr
  1452.         move.l    #$bfd500,(a4)        ;Set Timer A addresses
  1453.         move.l    #$bfd400,-(a4)
  1454.         move.l    #$bfde00,-(a4)
  1455. gotTimerB:    movea.l    craddr(pc),a0    ;get Control Register address
  1456.         and.b    #%10000000,(a0) ;clear CtrlReg bits 0 - 6
  1457.         move.b    d3,_timeropen    ;d3: 1 = TimerA 2 = TimerB
  1458.     ENDC
  1459.     IFNE    VBLANK
  1460.         moveq    #5,d0        ;INTB_VERTB
  1461.         lea    timerinterrupt(pc),a1
  1462.         jsr    -$a8(a6)    ;AddIntServer
  1463.         st    _timeropen
  1464.     ENDC
  1465.         clr.w    pstate
  1466.         moveq    #0,d0
  1467. initret:    movem.l    (sp)+,a4/a6/d2-d3
  1468.         rts
  1469. initerr:    move.l    d2,d0
  1470.         bra.s    initret
  1471.  
  1472. _AudioRem:    move.l    a6,-(sp)
  1473.         moveq    #0,d0
  1474.         lea    _timeropen(pc),a0
  1475.         move.b    (a0),d0
  1476.         beq.s    rem1
  1477. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  1478.         clr.b    (a0)
  1479.     IFNE    CIAB
  1480.         move.l    _ciaresource(pc),a6
  1481.         lea    timerinterrupt(pc),a1
  1482.         subq.b    #1,d0
  1483.         jsr    -$c(a6)        ;RemICRVector
  1484.     ENDC
  1485.     IFNE    VBLANK
  1486.         movea.l    4,a6
  1487.         lea    timerinterrupt(pc),a1
  1488.         moveq    #5,d0
  1489.         jsr    -$ae(a6)    ;RemIntServer
  1490.     ENDC
  1491. rem1:    
  1492.     IFNE    AUDDEV
  1493.         movea.l    4,a6
  1494.         lea    audiodevopen(pc),a0
  1495.         tst.b    (a0)
  1496.         beq.s    rem2
  1497.         move.w    #$000f,$dff096    ;stop audio DMA
  1498. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  1499.         clr.b    (a0)
  1500.         lea    allocreq(pc),a1
  1501.         jsr    -$1c2(a6)    ;CloseDevice()
  1502. rem2:        moveq    #0,d0
  1503.         move.b    sigbitnum(pc),d0
  1504.         bmi.s    rem3
  1505. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  1506.         jsr    -$150(a6)    ;FreeSignal()
  1507.     ENDC
  1508. rem3:        move.l    (sp)+,a6
  1509.         rts
  1510.  
  1511.     IFNE    MIDI
  1512. _GetSerial:    move.l    a6,-(sp)    ;Get serial port for MIDI
  1513.         bsr.s    GetSer2
  1514.         tst.l    d0        ;got the port??
  1515.         beq.s    rgser        ;yes
  1516.         movea.l    4,a6        ;no..try to flush serial.device:
  1517.         jsr    -$84(a6)        ;Forbid
  1518.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  1519.         lea    serdev(pc),a1        ;"serial.device"
  1520.         jsr    -$114(a6)        ;FindName
  1521.         tst.l    d0
  1522.         beq.s    serdnotf        ;no serial.device!!
  1523.         move.l    d0,a1
  1524.         jsr    -$1b6(a6)        ;RemDevice
  1525. serdnotf:    jsr    -$8a(a6)        ;and Permit
  1526.         bsr.s    GetSer2        ;now try it again...
  1527. rgser:        move.l    (sp)+,a6
  1528.         rts
  1529.  
  1530. GetSer2:    movea.l    4,a6
  1531.         moveq    #0,d0
  1532.         lea    miscresname(pc),a1
  1533.         jsr    -$1f2(a6)    ;OpenResource()
  1534.         move.l    d0,miscresbase
  1535.         tst.l    d0
  1536.         beq.s    gserror
  1537.         move.l    d0,a6
  1538.         lea    medname(pc),a1
  1539.         moveq    #0,d0        ;serial port
  1540.         jsr    -$6(a6)        ;AllocMiscResource()
  1541.         tst.l    d0
  1542.         bne.s    gserror
  1543.         st.b    serportalloc
  1544.         clr.w    intrson
  1545.         move.w    $dff01c,d0
  1546.         btst    #0,d0
  1547.         sne    intrson
  1548.         moveq    #0,d0        ;TBE
  1549.         lea    serinterrupt(pc),a1
  1550.         move.l    4,a6
  1551.         jsr    -$a2(a6)    ;SetIntVector()
  1552.         move.l    d0,prevtbe
  1553.         move.w    #$8001,$dff09a    ;TBE on!!
  1554.         move.w    #114,$dff032    ;set baud rate (SERPER)
  1555.         moveq    #0,d0
  1556.         rts
  1557. gserror:    moveq    #-1,d0
  1558.         rts
  1559.  
  1560. intrson:    dc.b    0,0
  1561.  
  1562. _FreeSerial:    move.l    a6,-(sp)
  1563.         tst.l    miscresbase
  1564.         beq.s    retfs
  1565.         tst.b    serportalloc
  1566.         beq.s    retfs
  1567.         move.w    #$0001,$dff09a    ;disable TBE
  1568.         movea.l    prevtbe(pc),a1
  1569.         moveq    #0,d0
  1570.         movea.l    4,a6
  1571.         jsr    -$a2(a6)    ;SetIntVector()
  1572.         tst.b    intrson
  1573.         beq.s    nofsstbe
  1574.         move.w    #$8001,$dff09a
  1575. nofsstbe:    movea.l    miscresbase(pc),a6
  1576.         moveq    #0,d0        ;serial port
  1577.         jsr    -$c(a6)        ;FreeMiscResource()
  1578.         clr.b    serportalloc
  1579.         clr.b    lastcmdbyte
  1580. retfs:        move.l    (sp)+,a6
  1581.         rts
  1582.  
  1583. prevtbe:    dc.l    0
  1584.  
  1585. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable...
  1586.         addq.b    #1,$126(a6)
  1587.         move.w    #1,$9c(a0)    ;clear intreq bit
  1588.         move.b    bytesinbuff(pc),d0
  1589.         beq.s    exsih        ;buffer empty
  1590.         movea.l    4(a1),a5    ;get buffer read pointer
  1591.         move.w    #$100,d1    ;Stop bit
  1592.         move.b    (a5),d1        ;get byte
  1593.         move.w    d1,$30(a0)    ;and push it out!! (SERDAT)
  1594.         addq.l    #1,a5        ;add 1
  1595.         cmpa.l    a1,a5        ;shall we reset ptr??
  1596.         bne.s    norrbuffptr    ;not yet..
  1597.         lea    sendbuffer(pc),a5
  1598. norrbuffptr:    subq.b    #1,d0        ;one less bytes in buffer
  1599.         move.b    d0,bytesinbuff    ;remember it
  1600.         move.l    a5,4(a1)    ;push new read pointer back
  1601. exsih:        subq.b    #1,$126(a6)
  1602.         bge.s    exsih0
  1603.         move.w    #$c000,$9a(a0)
  1604. exsih0:        rts
  1605.  
  1606. _AddMIDIData:    tst.b    serportalloc
  1607.         beq.s    retamd
  1608.         movem.l    a2/a6,-(sp)
  1609.         movea.l    4,a6
  1610.         move.w    #$4000,$dff09a    ;Disable interrupts
  1611.         addq.b    #1,$126(a6)    ;ExecBase->IDNestCnt
  1612.         move.b    bytesinbuff(pc),d1
  1613.         bne.s    noTBEreq
  1614.         move.w    #$8001,$dff09c    ;request TBE
  1615. noTBEreq:    lea    buffptr(pc),a2    ;end of buffer (ptr)
  1616.         movea.l    (a2),a1        ;buffer pointer
  1617. adddataloop:    move.b    (a0)+,d1    ;get byte
  1618.         bpl.s    norscheck    ;this isn't a status byte
  1619.         cmp.b    #$ef,d1        ;forget system messages
  1620.         bhi.s    norscheck
  1621.         cmp.b    lastcmdbyte(pc),d1 ;same as previos status byte??
  1622.         beq.s    samesb        ;yes, skip
  1623.         move.b    d1,lastcmdbyte    ;no, don't skip but remember!!
  1624. norscheck:    move.b    d1,(a1)+    ;push it to midi send buffer
  1625.         addq.b    #1,bytesinbuff
  1626. samesb:        cmpa.l    a2,a1    ;end of buffer??
  1627.         bne.s    noresbuffptr    ;no, no!!
  1628.         lea    sendbuffer(pc),a1 ;better reset it to avoid trashing
  1629. noresbuffptr:    subq.b    #1,d0
  1630.         bne.s    adddataloop
  1631.         move.l    a1,(a2)        ;push new buffer ptr back
  1632. overflow:    subq.b    #1,$126(a6)
  1633.         bge.s    retamd1
  1634.         move.w    #$c000,$dff09a    ;enable interrupts again
  1635. retamd1:    movem.l    (sp)+,a2/a6
  1636. retamd:        rts
  1637. sendbuffer:    ds.b    128
  1638. buffptr:    dc.l    sendbuffer
  1639. readbuffptr:    dc.l    sendbuffer
  1640. miscresbase:    dc.l    0
  1641. lastcmdbyte:    dc.b    0
  1642.     ENDC
  1643.         even
  1644.     IFNE    MIDI
  1645. preschgdata:    dc.b    0,0
  1646. noteondata:    dc.l    0
  1647. serportalloc:    dc.b    0
  1648. bytesinbuff:    dc.b    0
  1649.     ENDC
  1650.     IFNE    AUDDEV
  1651. audiodevopen:    dc.b    0
  1652. sigbitnum:    dc.b    -1
  1653.     ENDC
  1654. _timeropen:    dc.b    0
  1655.         even
  1656.     IFNE    CIAB
  1657. _ciaresource:    dc.l    0
  1658. craddr:        dc.l    0
  1659.         dc.l    0    ;tloaddr
  1660.         dc.l    0    ;thiaddr
  1661.     ENDC
  1662. _module:    dc.l    0
  1663. timerinterrupt:    dc.w    0,0,0,0,0
  1664.         dc.l    timerintname,0,_IntHandler
  1665.     IFNE    MIDI
  1666. serinterrupt:    dc.w    0,0,0,0,0
  1667.         dc.l    serintname,buffptr,SerIntHandler
  1668.     ENDC
  1669.     IFNE    AUDDEV
  1670. allocport:    dc.l    0,0    ;succ, pred
  1671.         dc.b    4,0    ;NT_MSGPORT
  1672.         dc.l    0    ;name
  1673.         dc.b    0,0    ;flags = PA_SIGNAL
  1674.         dc.l    0    ;task
  1675. reqlist:    dc.l    0,0,0    ;list head, tail and tailpred
  1676.         dc.b    5,0
  1677. allocreq:    dc.l    0,0
  1678.         dc.b    5,127    ;NT_MESSAGE, use maximum priority (127)
  1679.         dc.l    0,allocport    ;name, replyport
  1680.         dc.w    68        ;length
  1681.         dc.l    0    ;io_Device
  1682.         dc.l    0    ;io_Unit
  1683.         dc.w    0    ;io_Command
  1684.         dc.b    0,0    ;io_Flags, io_Error
  1685.         dc.w    0    ;ioa_AllocKey
  1686.         dc.l    sttempo    ;ioa_Data
  1687.         dc.l    1    ;ioa_Length
  1688.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  1689.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  1690. audiodevname:    dc.b    'audio.device',0
  1691.     ENDC
  1692.     IFNE    CIAB
  1693. ciabname:    dc.b    'ciab.resource',0
  1694.     ENDC
  1695. timerintname:    dc.b    'MEDTimerInterrupt',0
  1696.     IFNE    MIDI
  1697. serintname:    dc.b    'MEDSerialInterrupt',0
  1698.     ENDC
  1699.     IFNE    MIDI
  1700. miscresname:    dc.b    'misc.resource',0
  1701. serdev:        dc.b    'serial.device',0
  1702.     ENDC
  1703. medname:    dc.b    'MED - Player routine',0 ;yeah, our name
  1704.         even
  1705.     IFNE    SYNTH
  1706. _synthper:    dc.w 3424,3232,3048,2880,2712,2560,2416,2280,2152,2032
  1707.         dc.w 1920,1812,1712,1616,1524,1440,1356,1280,1208,1140
  1708.         dc.w 1076,1016,960,906
  1709.     ENDC
  1710. _periods:    dc.w 856,808,762,720,678,640,604,570,538,508,480,453
  1711.         dc.w 428,404,381,360,339,320,302,285,269,254,240,226
  1712.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1713.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1714.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1715.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1716.  
  1717. holdvals:    ds.b 63
  1718. decays:        ds.b 63
  1719.         section "chipdata",data_c
  1720. _chipzero:    dc.l    0
  1721. _playmodule:    incbin    "module" ;; <<< MODULE NAME HERE
  1722.  
  1723. ; the track-data structure definition:
  1724.         rsreset
  1725. trk_prevnote    rs.b    1    ;previous note number
  1726. trk_previnstr    rs.b    1    ;previous instrument number
  1727. trk_prevvol    rs.b    1    ;previous volume
  1728. trk_prevmidich    rs.b    1    ;previous MIDI channel
  1729. trk_cmd        rs.b    1    ;command (the 3rd number from right)
  1730. trk_cmdqual    rs.b    1    ;command qualifier (infobyte, databyte..)
  1731. trk_prevmidin    rs.b    1    ;previous MIDI note
  1732. trk_noteoffcnt    rs.b    1    ;note-off counter (hold)
  1733. trk_inithold    rs.b    1    ;default hold for this instrument
  1734. trk_initdecay    rs.b    1    ;default decay for....
  1735. trk_stransp    rs.b    1    ;instrument transpose
  1736. trk_pad        rs.b    1
  1737. trk_previnstra    rs.l    1    ;address of the previous instrument data
  1738. trk_trackvol    rs.w    1    ;relative volume of track (premultiplied)
  1739. ;    the following data only on tracks 0 - 3
  1740. trk_prevper    rs.w    1    ;previous period
  1741. trk_audioaddr    rs.l    1    ;hardware audio channel base address
  1742. trk_sampleptr    rs.l    1    ;pointer to sample
  1743. trk_samplelen    rs.w    1    ;length (>> 1)
  1744. trk_porttrgper    rs.w    1    ;portamento (cmd 3) target period
  1745. trk_vibroffs    rs.b    1    ;vibrato table offset
  1746. trk_vibrspdsz    rs.b    1    ;vibrato speed/size (cmd 4 qualifier)
  1747. trk_synthptr    rs.l    1    ;pointer to synthetic/hybrid instrument
  1748. trk_arpgoffs    rs.w    1    ;SYNTH: current arpeggio offset
  1749. trk_arpsoffs    rs.w    1    ;SYNTH: arpeggio restart offset
  1750. trk_volxcnt    rs.b    1    ;SYNTH: volume execute counter
  1751. trk_wfxcnt    rs.b    1    ;SYNTH: waveform execute counter
  1752. trk_volcmd    rs.w    1    ;SYNTH: volume command pointer
  1753. trk_wfcmd    rs.w    1    ;SYNTH: waveform command pointer
  1754. trk_volwait    rs.b    1    ;SYNTH: counter for WAI (volume list)
  1755. trk_wfwait    rs.b    1    ;SYNTH: counter for WAI (waveform list)
  1756. trk_synthvibspd    rs.w    1    ;SYNTH: vibrato speed
  1757. trk_wfchgspd    rs.w    1    ;SYNTH: period change
  1758. trk_volchgspd    rs.b    1    ;SYNTH: volume change
  1759. trk_prevnote2    rs.b    1    ;SYNTH: previous note
  1760. trk_initvolxspd    rs.b    1    ;SYNTH: volume execute speed
  1761. trk_initwfxspd    rs.b    1    ;SYNTH: waveform execute speed
  1762. trk_perchg    rs.w    1    ;SYNTH: curr. period change from trk_prevper
  1763. trk_synviboffs    rs.w    1    ;SYNTH: vibrato pointer
  1764. trk_synvibdep    rs.w    1    ;SYNTH: vibrato depth
  1765. trk_synvol    rs.b    1    ;SYNTH: current volume
  1766. trk_synthtype    rs.b    1    ;>0 = synth, -1 = hybrid, 0 = no synth
  1767. trk_periodtbl    rs.l    1    ;pointer to period table
  1768. trk_prevportspd    rs.w    1    ;portamento (cmd 3) speed
  1769. trk_decay    rs.b    1    ;decay
  1770. trk_fadespd    rs.b    1    ;decay speed
  1771.         end
  1772.