home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 497b.lha / MED_v3.0 / Programmers / MODPlayer / easyplayer.a next >
Encoding:
Text File  |  1991-04-03  |  48.7 KB  |  1,765 lines

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