home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 591b.lha / OctaMED_v1.0b / Programmers / MODPlayer / modplayer.a < prev    next >
Text File  |  1991-04-30  |  50KB  |  1,735 lines

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