home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 1 / FFMCD01.bin / bbs / libdisks / d700t799 / disk718.lha / BootPic / BootPic_source.lz / modplayer.i < prev    next >
Encoding:
Text File  |  1992-08-13  |  74.8 KB  |  1,772 lines

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