home *** CD-ROM | disk | FTP | other *** search
/ Merciful 3 / Merciful_Release_3.bin / software / o / octamed / octamedv6.12.lha / programmers / proplayer.a < prev    next >
Text File  |  1995-05-31  |  97KB  |  3,508 lines

  1. ;============================================================================
  2. ;    proplayer.a
  3. ;    ~~~~~~~~~~~
  4. ; $VER: proplayer 6.1 (31.05.1995)
  5. ;
  6. ; The music player routine for MMD0/MMD1/MMD2 MED/OctaMED
  7. ; four-channel modules.
  8. ;
  9. ; Copyright © 1995 Teijo Kinnunen and RBF Software.
  10. ;
  11. ; Written by Teijo Kinnunen.
  12. ; Comments/questions/bug reports can be sent to:
  13. ;    Teijo Kinnunen
  14. ;    Oksantie 19
  15. ;    FIN-86300  OULAINEN
  16. ;    FINLAND
  17. ;    email: kinnunen@stekt.oulu.fi
  18. ;
  19. ; See OctaMED docs for conditions about using these routines.
  20. ; Comments/questions about distribution and usage conditions
  21. ; should be directed to RBF Software. (Email: rbfsoft@cix.compulink.co.uk)
  22. ;
  23. ;============================================================================
  24.  
  25. ;****** Feature control ******
  26. ;
  27. MIDI        EQU 0    ;1 = include MIDI code
  28. AUDDEV        EQU 1    ;1 = allocate channels using audio.device
  29. SYNTH        EQU 1    ;1 = include synth-sound handler
  30. CHECK        EQU 1    ;1 = do range checkings (track, sample in mem etc.)
  31. RELVOL        EQU 1    ;1 = include relative volume handling code
  32. IFFMOCT        EQU 1    ;1 = play IFF multi-octave samples/ExtSamples correctly
  33. HOLD        EQU 1    ;1 = handle hold/decay
  34. PLAYMMD0    EQU 1    ;1 = play old MMD0 modules
  35. AURA        EQU 0    ;1 = support the Aura sampler
  36. ;
  37. ; The less features you include, the faster and shorter the play-routine
  38. ; will be.
  39. ;
  40. ; NOTE: Using the Aura will cause Enforcer hits (LONG-READ/WRITE at addr $70).
  41. ; This is normal, and can't be avoided.
  42.  
  43. ;****** Timing control ******
  44. ;
  45. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  46. CIAB    EQU    1    ;1 = use CIA timers (default)
  47. ;
  48. ; Please use CIAB whenever possible to avoid problems with variable
  49. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  50. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  51. ; then you just call _IntHandler for each timing pulse.
  52.  
  53. ;============================================================================
  54.  
  55. ;If you are making a demo/game with only a single tune you'd like to
  56. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  57. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  58. ;You have to insert the module name to the INCBIN statement (located near the
  59. ;end of this file, on line 2052).
  60.  
  61. EASY    EQU    0
  62.  
  63. ;Call _startmusic to play the music, and _endmusic to stop it (before
  64. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  65. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  66. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  67.  
  68. ;============================================================================
  69.  
  70. ; The MMD structure offsets
  71. mmd_id        EQU    0
  72. mmd_modlen    EQU    4
  73. mmd_songinfo    EQU    8
  74. ; these two for MMD2s only!
  75. mmd_psecnum    EQU    12
  76. mmd_pseq    EQU    14
  77. ;
  78. mmd_blockarr    EQU    16
  79. mmd_smplarr    EQU    24
  80. mmd_expdata    EQU    32
  81. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  82. mmd_pblock    EQU    42
  83. mmd_pline    EQU    44
  84. mmd_pseqnum    EQU    46
  85. mmd_counter    EQU    50
  86. mmd_songsleft    EQU    51
  87.  
  88. ; The Song structure
  89. ; Instrument data here (504 bytes = 63 * 8)
  90. msng_numblocks    EQU    504
  91. msng_songlen    EQU    506
  92. msng_playseq    EQU    508
  93. msng_deftempo    EQU    764
  94. msng_playtransp    EQU    766
  95. msng_flags    EQU    767
  96. msng_flags2    EQU    768
  97. msng_tempo2    EQU    769
  98. ; msng_trkvol applies to MMD0/MMD1 only.
  99. msng_trkvol    EQU    770
  100. msng_mastervol    EQU    786
  101. msng_numsamples    EQU    787
  102. ; Fields below apply to MMD2 modules only.
  103. msng_pseqs    EQU    508
  104. msng_sections    EQU    512
  105. msng_trkvoltbl    EQU    516
  106. msng_numtracks    EQU    520
  107. msng_numpseqs    EQU    522
  108.  
  109. ; Instrument data
  110. inst_repeat    EQU    0
  111. inst_replen    EQU    2
  112. inst_midich    EQU    4
  113. inst_midipreset    EQU    5
  114. inst_svol    EQU    6
  115. inst_strans    EQU    7
  116.  
  117. ; Audio hardware offsets
  118. ac_ptr    EQU    $00
  119. ac_len    EQU    $04
  120. ac_per    EQU    $06
  121. ac_vol    EQU    $08
  122.  
  123. ; Trackdata sizes
  124. T03SZ        EQU    106
  125. T415SZ        EQU    22
  126. ;offset of trk_audioaddr
  127. TAAOFFS        EQU    24
  128. TTMPVOLOFFS    EQU    102
  129.  
  130. ; Maximum number of tracks allowed. If you don't need this much tracks,
  131. ; you can decrease the number to save some space. (Be sure that the
  132. ; song really has no more than MAX_NUMTRACKS tracks. Minimum allowed
  133. ; value = 4.)
  134. MAX_NUMTRACKS    EQU    64
  135.  
  136. ; This value is used for MMD0/1 conversion. If MAX_NUMTRACKS <= 16,
  137. ; this should be the same. If MAX_NUMTRACKS > 16, this should be 16.
  138. MAX_MMD1_TRACKS    EQU    16
  139.  
  140. ; Aura output handling routines
  141.     IFNE    AURA
  142.         ;also includes the SECTION cmd...
  143.         INCLUDE    "aura.a"
  144.     ENDC
  145.     IFEQ    AURA
  146.         SECTION    "text",CODE
  147.     ENDC
  148.  
  149.     IFNE    EASY
  150.  
  151.         XDEF    _startmusic,_endmusic
  152.  
  153. _startmusic    lea    easymod,a2
  154.         bsr.s    _RelocModule
  155.         bsr.w    _InitPlayer
  156.         lea    easymod,a0
  157.         bra.w    _PlayModule
  158.  
  159. _endmusic    bra.w    _RemPlayer
  160. ; ***** The relocation routine *****
  161. reloci        move.l    24(a2),d0
  162.         beq.s    xloci
  163.         movea.l    d0,a0
  164.         moveq   #0,d0
  165.         move.b  msng_numsamples(a1),d0
  166.         subq.b  #1,d0
  167. relocs        bsr.s   relocentr
  168.         move.l    -4(a0),d3
  169.         beq.s    nosyn
  170.         move.l    d3,a3
  171.         tst.w    4(a3)
  172.         bpl.s    nosyn
  173.         move.w    20(a3),d2
  174.         lea    278(a3),a3
  175.         subq.w    #1,d2
  176. relsyn        add.l    d3,(a3)+
  177.         dbf    d2,relsyn
  178. nosyn        dbf     d0,relocs
  179. xloci        rts
  180. norel        addq.l    #4,a0
  181.         rts
  182. relocentr    tst.l   (a0)
  183.         beq.s   norel
  184.         add.l   d1,(a0)+
  185.         rts
  186. _RelocModule    movem.l    a2-a4/d2-d4,-(sp)
  187.         move.l  a2,d1
  188.         bsr.s    relocp
  189.         movea.l mmd_songinfo(a2),a1
  190.         bsr.s    reloci
  191.         move.b    mmd_songsleft(a2),d4
  192. rel_lp        bsr.s    relocb
  193.         cmp.b    #'2',3(a2)
  194.         bne.s    norelmmd2
  195.         bsr.w    relocmmd2sng
  196. norelmmd2    move.l    mmd_expdata(a2),d0
  197.         beq.s    rel_ex
  198.         move.l    d0,a0
  199.         bsr.s    relocentr
  200.         bsr.s    relocentr
  201.         addq.l    #4,a0
  202.         bsr.s    relocentr
  203.         addq.l    #4,a0
  204.         bsr.s    relocentr
  205.         addq.l    #8,a0
  206.         bsr.s    relocentr
  207.         addq.l    #4,a0
  208.         bsr.s    relocentr
  209.         bsr.s    relocentr
  210.         addq.l    #4,a0
  211.         bsr.s    relocentr
  212.         bsr.s    relocmdd
  213.         subq.b    #1,d4
  214.         bcs.s    rel_ex
  215.         move.l    d0,a0
  216.         move.l    (a0),d0
  217.         beq.s    rel_ex
  218.         move.l    d0,a2
  219.         bsr.s    relocp
  220.         movea.l 8(a2),a1
  221.         bra.s    rel_lp
  222. rel_ex        movem.l    (sp)+,d2-d4/a2-a4
  223.         rts
  224. relocp        lea    mmd_songinfo(a2),a0
  225.         bsr.s    relocentr
  226.         addq.l    #4,a0
  227.         bsr.s    relocentr
  228.         addq.l    #4,a0
  229.         bsr.s    relocentr
  230.         addq.l    #4,a0
  231.         bra.s    relocentr
  232. relocb        move.l    mmd_blockarr(a2),d0
  233.         beq.s    xlocb
  234.         movea.l    d0,a0
  235.         move.w  msng_numblocks(a1),d0
  236.         subq.b  #1,d0
  237. rebl        bsr    relocentr
  238.         dbf     d0,rebl
  239.         cmp.b    #'T',3(a2)
  240.         beq.s    xlocb
  241.         cmp.b    #'1',3(a2)
  242.         bge.s    relocbi
  243. xlocb        rts
  244. relocmdd    move.l    d0,-(sp)
  245.         tst.l    -(a0)
  246.         beq.s    xlocmdd
  247.         movea.l    (a0),a0
  248.         move.w    (a0),d0
  249.         addq.l    #8,a0
  250. mddloop        beq.s    xlocmdd
  251.         bsr    relocentr
  252.         bsr.s    relocdmp
  253.         subq.w    #1,d0
  254.         bra.s    mddloop
  255. xlocmdd        move.l    (sp)+,d0
  256.         rts
  257. relocdmp    move.l    -4(a0),d3
  258.         beq.s    xlocdmp
  259.         exg.l    a0,d3
  260.         addq.l    #4,a0
  261.         bsr    relocentr
  262.         move.l    d3,a0
  263. xlocdmp        rts
  264. relocbi        move.w    msng_numblocks(a1),d0
  265.         move.l    a0,a3
  266. biloop        subq.w    #1,d0
  267.         bmi.s    xlocdmp
  268.         move.l    -(a3),a0
  269.         addq.l    #4,a0
  270.         bsr    relocentr
  271.         tst.l    -(a0)
  272.         beq.s    biloop
  273.         move.l    (a0),a0
  274.         bsr    relocentr
  275.         bsr    relocentr
  276.         addq.l    #4,a0
  277.         bsr    relocentr
  278.         tst.l    -(a0)
  279.         bne.s    relocpgtbl
  280.         bra.s    biloop
  281. relocmmd2sng    move.l    mmd_songinfo(a2),a0
  282.         lea    msng_pseqs(a0),a0
  283.         bsr    relocentr
  284.         bsr    relocentr
  285.         bsr    relocentr
  286.         move.w    2(a0),d0
  287.         move.l    -12(a0),a0
  288.         subq.w    #1,d0
  289. psqtblloop    bsr    relocentr
  290.         dbf    d0,psqtblloop
  291.         rts
  292. relocpgtbl    movea.l    (a0),a4
  293.         move.w    (a4),d2
  294.         subq.w    #1,d2
  295.         lea    4(a4),a0
  296. pgtblloop    bsr    relocentr
  297.         dbf    d2,pgtblloop
  298.         bra    biloop
  299.     ENDC
  300.  
  301. ; -------- _ChannelOff: Turn off a channel -------------------------------
  302. _ChannelOff:    ;d0 = channel #
  303.         lea    DB,a0
  304.         lea    trackdataptrs-DB(a0),a1
  305.         lsl.w    #2,d0
  306.         adda.w    d0,a1
  307.         lsr.w    #2,d0
  308.         movea.l    (a1),a1
  309.         move.b    trk_outputdev(a1),d1
  310.     IFNE    AURA
  311.         beq.s    choff_outstd
  312.         subq.b    #1,d1
  313.         bne.s    notamigatrk    ;unknown type... do nothing
  314.         jmp    _StopAura(pc)    ;AURA off
  315. choff_outstd
  316.     ENDC
  317.     IFEQ    AURA
  318.         bne.s    notamigatrk
  319.     ENDC
  320.     IFNE    MIDI
  321.         move.b    trk_prevmidin(a1),d1    ;first: is it MIDI??
  322.         beq.s    notcomidi    ;not a midi note
  323. ; -------- TURN OFF MIDI TRACK -------------------------------------------
  324.         lea    noteondata-DB(a0),a0
  325. choff_midi:    clr.b    trk_prevmidin(a1)
  326.         move.b    d1,1(a0)
  327.         bmi.s    notamigatrk
  328.         move.b    trk_prevmidich(a1),(a0)    ;prev midi channel
  329.         clr.b    2(a0)
  330.         or.b    #$90,(a0)        ;note off
  331.         moveq    #3,d0
  332.         bra.w    _AddMIDIData
  333.     ENDC
  334. notcomidi:    cmp.b    #4,d0
  335.         bge.s    notamigatrk
  336. ; -------- TURN OFF AMIGA-CHANNEL ----------------------------------------
  337.     IFNE    SYNTH
  338.         clr.l    trk_synthptr(a1)
  339.         clr.b    trk_synthtype(a1)
  340.     ENDC
  341.         clr.w    trk_soffset(a1)
  342.         moveq    #1,d1
  343.         lsl.w    d0,d1
  344.         move.w    d1,$dff096
  345. notamigatrk:    rts
  346.  
  347. ; -------- SoundOff: Turn off all channels -------------------------------
  348. SoundOff:    move.l    d2,-(sp)
  349.         moveq    #MAX_NUMTRACKS-1,d2
  350. SO_loop0    move.l    d2,d0
  351.         bsr.s    _ChannelOff
  352.         dbf    d2,SO_loop0
  353.         clr.l    _module        ;play nothing
  354.         move.l    (sp)+,d2
  355. SO_rts        rts
  356.  
  357. ; -------- _PlayNote: The note playing routine ---------------------------
  358. _PlayNote:    ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  359. ; -------- CHECK INSTRUMENT (existence, type) ----------------------------
  360.         move.l    a3,d4
  361.         beq.s    SO_rts
  362.         moveq    #0,d4
  363.         bset    d7,d4    ;d4 is mask for this channel
  364.         movea.l    mmd_smplarr(a2),a0
  365.         add.w    d3,d3            ;d3 = instr.num << 2
  366.         add.w    d3,d3
  367.         move.l    0(a0,d3.w),d5        ;get address of instrument
  368.     IFNE    MIDI
  369.         bne.s    inmem
  370.         tst.b    inst_midich(a3)        ;is MIDI channel set?
  371.     ENDC
  372.     IFNE    CHECK
  373.         beq.w    pnote_rts        ; NO!!!
  374.     ENDC
  375. ; -------- ADD TRANSPOSE -------------------------------------------------
  376. inmem        add.b    msng_playtransp(a4),d1    ;add play transpose
  377.         add.b    inst_strans(a3),d1    ;and instr. transpose
  378.     IFNE    AURA
  379.         cmp.w    #3,d7
  380.         bne.s    pn_norelch3
  381.         tst.b    playing_aura-DB(a6)
  382.         bne.s    pn_offaura
  383. pn_norelch3
  384.     ENDC
  385.         move.b    trk_outputdev(a5),d3
  386.         beq.s    pn_offami
  387.     IFNE    AURA
  388.         subq.b    #1,d3
  389.         bne.s    noprevmidi
  390. pn_offaura    jsr    _StopAura(pc)
  391.     ENDC
  392.         bra.s    noprevmidi        ;dunno.. unsupported type
  393.     
  394. ; -------- TURN OFF CHANNEL DMA, IF REQUIRED -----------------------------
  395. pn_offami    cmp.b    #4,d7
  396.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  397.         move.l    d5,a1
  398.     IFNE    SYNTH
  399.         tst.l    d5
  400.         beq.s    stpdma
  401.         tst.b    trk_synthtype(a5)
  402.         ble.s    stpdma        ;prev. type = sample/hybrid
  403.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  404.         beq.s    nostpdma
  405.     ENDC
  406. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  407. nostpdma:
  408.     IFNE    SYNTH
  409.         clr.l    trk_synthptr(a5)
  410.     ENDC
  411. nodmaoff:    subq.b    #1,d1
  412.     IFNE    MIDI
  413. ; -------- KILL PREVIOUS MIDI NOTE ---------------------------------------
  414.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  415.         beq.s    noprevmidi
  416.         clr.b    trk_prevmidin(a5)
  417.         lea    noteondata+2-DB(a6),a0
  418.         clr.b    (a0)
  419.         move.b    d3,-(a0)
  420.         bmi.s    noprevmidi
  421.         move.b    trk_prevmidich(a5),-(a0) ;prev midi channel
  422.         or.b    #$90,(a0)         ;note off
  423.         move.w    d1,-(sp)
  424.         moveq    #3,d0
  425.         bsr.w    _AddMIDId
  426.         move.w    (sp)+,d1
  427. noprevmidi
  428. ; -------- IF MIDI NOTE, CALL MIDI NOTE ROUTINE --------------------------
  429.         tst.b    inst_midich(a3)
  430.         bne.w    handleMIDInote
  431.     ENDC
  432. ; -------- TEST OUTPUT DEVICE AND BRANCH IF NOT STD ----------------------
  433.     IFEQ    MIDI
  434. noprevmidi
  435.     ENDC
  436.         tst.b    trk_outputdev(a5)
  437.         bne.w    handlenonstdout
  438. ; -------- SET SOME AMIGA-CHANNEL PARAMETERS -----------------------------
  439.     IFNE    CHECK
  440.         cmp.w    #4,d7        ;track > 3???
  441.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  442.     ENDC
  443. ; handle decay (for tracks 0 - 3 only!!)
  444.     IFNE    HOLD
  445.         clr.b    trk_fadespd(a5)        ;no fade yet..
  446.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  447.     ENDC
  448.         clr.w    trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  449.         or.w    d4,dmaonmsk-DB(a6)
  450.         move.l    d5,a0
  451.     IFNE    SYNTH
  452. ; -------- IF SYNTH NOTE, CALL SYNTH ROUTINE -----------------------------
  453.         tst.w    4(a0)
  454.         bmi.w    handleSynthnote
  455.         clr.b    trk_synthtype(a5)
  456.     ENDC
  457. ; -------- CHECK NOTE RANGE ----------------------------------------------
  458. tlwtst0        tst.b    d1
  459.         bpl.s    notenot2low
  460.         add.b    #12,d1    ;note was too low, octave up
  461.         bra.s    tlwtst0
  462. notenot2low    cmp.b    #62,d1
  463.         ble.s    endpttest
  464.         sub.b    #12,d1    ;note was too high, octave down
  465. endpttest
  466.         moveq    #0,d2
  467.         moveq    #0,d3
  468.         moveq    #6,d4    ;skip (stereo+hdr) offset
  469.         lea    _periodtable+32-DB(a6),a1
  470.         move.b    trk_finetune(a5),d2    ;finetune value
  471.         add.b    d2,d2
  472.         add.b    d2,d2        ;multiply by 4...
  473.         ext.w    d2        ;extend
  474.         movea.l    0(a1,d2.w),a1    ;period table address
  475.         move.w    4(a0),d0    ;(Instr hdr in a0)
  476.         btst    #5,d0
  477.         beq.s    gid_nostereo
  478.         move.b    d7,d5
  479.         and.b    #3,d5
  480.         beq.s    gid_nostereo    ;ch 0/4 = play left (norm.)
  481.         cmp.b    #3,d5
  482.         beq.s    gid_nostereo    ;also for ch 3/7
  483.         add.l    (a0),d4        ;play right channel
  484. gid_nostereo
  485.     IFNE    IFFMOCT
  486.         and.w    #$F,d0
  487.         bne.s    gid_notnormal    ;note # in d1 (0 - ...)
  488.     ENDC
  489. gid_cont_ext    move.l    a1,trk_periodtbl(a5)
  490.         add.b    d1,d1
  491.         move.w    0(a1,d1.w),d5 ;put period to d5
  492.         move.l    a0,d0
  493.         move.l    (a0),d1        ;length
  494.         add.l    d4,d0        ;skip hdr and stereo
  495.         add.l    d0,d1        ;sample end pointer
  496.         move.w    inst_repeat(a3),d2
  497.         move.w    inst_replen(a3),d3
  498.     IFNE    IFFMOCT
  499.         bra    gid_setrept
  500. gid_addtable    dc.b    0,6,12,18,24,30
  501. gid_divtable    dc.b    31,7,3,15,63,127
  502. gid_notnormal    cmp.w    #7,d0
  503.         blt.s    gid_not_ext
  504.         suba.w    #48,a1
  505.         bra.s    gid_cont_ext
  506. gid_not_ext    move.l    d7,-(sp)
  507.         moveq    #0,d7
  508.         move.w    d1,d7
  509.         divu    #12,d7    ;octave #
  510.         move.l    d7,d5
  511.         cmp.w    #6,d7    ;if oct > 5, oct = 5
  512.         blt.s    nohioct
  513.         moveq    #5,d7
  514. nohioct        swap    d5    ;note number in this oct (0-11) is in d5
  515.         move.l    (a0),d1
  516.         cmp.w    #6,d0
  517.         ble.s    nounrecit
  518.         moveq    #6,d0
  519. nounrecit    add.b    gid_addtable-1(pc,d0.w),d7
  520.         move.b    gid_divtable-1(pc,d0.w),d0
  521.         divu    d0,d1    ;get length of the highest octave
  522.         swap    d1
  523.         clr.w    d1
  524.         swap    d1
  525.         move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  526.         move.w    inst_repeat(a3),d2
  527.         move.w    inst_replen(a3),d3
  528.         moveq    #0,d6
  529.         move.b    shiftcnt(pc,d7.w),d6
  530.         lsl.w    d6,d2
  531.         lsl.w    d6,d3
  532.         lsl.w    d6,d1
  533.         move.b    mullencnt(pc,d7.w),d6
  534.         mulu    d6,d0        ;offset of this oct from 1st oct
  535.         add.l    a0,d0        ;add base address to offset
  536.         add.l    d4,d0        ;skip header + stereo
  537.         add.l    d0,d1
  538.         move.l    a1,trk_periodtbl(a5)
  539.         add.b    octstart(pc,d7.w),d5
  540.         add.b    d5,d5
  541.         move.w    0(a1,d5.w),d5
  542.         move.l    (sp)+,d7
  543.         bra.s    gid_setrept
  544. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
  545.         dc.b    3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
  546. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
  547.         dc.b    7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
  548. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
  549.         dc.b    0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
  550.     ENDC
  551. gid_setrept    add.l    d2,d2
  552.         add.l    d0,d2        ;rep. start pointer
  553.         cmp.w    #1,d3
  554.         bhi.s    gid_noreplen2
  555.         moveq    #0,d3        ;no repeat
  556.         bra.s    gid_cont
  557. gid_noreplen2    add.l    d3,d3
  558.         add.l    d2,d3        ;rep. end pointer
  559.  
  560. ; -------- CALCULATE START/END ADDRESSES ---------------------------------
  561. gid_cont    moveq    #0,d4
  562.         move.w    trk_soffset(a5),d4
  563.         add.l    d4,d0
  564.         cmp.l    d0,d1
  565.         bhi.s    pn_nooffsovf
  566.         sub.l    d4,d0
  567. pn_nooffsovf    movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  568.         move.l    d0,(a1)+        ;push ac_ptr
  569.         moveq    #0,d4
  570.         move.b    trk_previnstr(a5),d4
  571.         lea    flags-DB(a6),a0
  572.         btst    #0,0(a0,d4.w)        ;test flags.SSFLG_LOOP
  573.         bne.s    repeat
  574.         
  575.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  576.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  577.         sub.l    d0,d1
  578.         lsr.l    #1,d1            ;shift length right
  579.         move.w    d1,(a1)+        ;and push to ac_len
  580.         bra.s    retsn1
  581.  
  582. repeat        move.l    d2,trk_sampleptr(a5)
  583.         move.l    d3,d1
  584.         sub.l    d0,d1
  585.         lsr.l    #1,d1
  586.         move.w    d1,(a1)+    ;ac_len
  587.         sub.l    d2,d3
  588.         lsr.l    #1,d3
  589.         move.w    d3,trk_samplelen(a5)
  590.                 
  591. retsn1        move.w    d5,trk_prevper(a5)
  592.     IFNE    SYNTH
  593.         tst.b    trk_synthtype(a5)
  594.         bne.w    hSn2
  595.     ENDC
  596. pnote_rts    rts
  597.  
  598. handlenonstdout
  599.     IFNE    AURA
  600.         move.b    trk_outputdev(a5),d0
  601.         subq.b    #1,d0
  602.         bne.s    hnso_notaura
  603. ; -------- AURA NOTE PLAYER ROUTINE --------------------------------------
  604. ;    a0 = sample pointer, already set
  605.         moveq    #0,d0
  606.         move.w    trk_soffset(a5),d0
  607.         lea    _periodtable+32-DB(a6),a1
  608.         move.b    trk_finetune(a5),d2    ;finetune value
  609.         add.b    d2,d2
  610.         add.b    d2,d2
  611.         ext.w    d2
  612.         movea.l    0(a1,d2.w),a1        ;period table address
  613.         add.b    d1,d1
  614.         move.w    0(a1,d1.w),d1
  615.         moveq    #0,d2            ;end offset = 0
  616.         jsr    _PlayAura(pc)
  617. hnso_notaura
  618.     ENDC
  619.         rts
  620.  
  621.     IFNE    MIDI
  622. ; -------- MIDI NOTE PLAYER ROUTINE --------------------------------------
  623. handleMIDInote:
  624.     IFNE    PLAYMMD0
  625.         cmp.b    #'1',3(a2)
  626.         bge.s    plr_mmd1_3
  627.         add.b    #24,d1
  628. plr_mmd1_3
  629.     ENDC
  630. ; -------- CHECK & SCALE VOLUME ------------------------------------------
  631.         move.b    trk_prevvol(a5),d2 ;temporarily save the volume
  632.     IFNE    RELVOL
  633. ; -------- GetRelVol: Calculate track volume -----------------------------
  634.         ext.w    d2
  635.         mulu    trk_trackvol(a5),d2
  636.         lsr.w    #7,d2
  637.     ENDC
  638.     IFEQ    RELVOL
  639.         lsl.b    #1,d2
  640.     ENDC
  641.         subq.b    #1,d2        ;if 128 => 127
  642.         bpl.s    hmn_notvolu0
  643.         moveq    #0,d2
  644. hmn_notvolu0
  645.         moveq    #0,d5
  646. ; -------- CHECK MIDI CHANNEL --------------------------------------------
  647.         move.b    inst_midich(a3),d5 ;get midi chan of this instrument
  648.         bpl.s    hmn_nosmof    ;bit 7 clear
  649.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  650.         bra.s    hmn_smof
  651. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  652. hmn_smof    and.b    #$1F,d5        ;clear all flag bits etc...
  653.         subq.b    #1,d5        ;from 1-16 to 0-15
  654.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  655.  
  656. ; -------- CHECK MIDI PRESET ---------------------------------------------
  657.         moveq    #0,d0
  658.         move.b    trk_previnstr(a5),d0
  659.         add.w    d0,d0
  660.         lea    ext_midipsets-DB(a6),a1
  661.         move.w    0(a1,d0.w),d0    ;get preset #
  662.         beq.s    nochgpres    ;zero = no preset
  663.         lea    prevmidicpres-DB(a6),a1
  664.         adda.w    d5,a1
  665.         adda.w    d5,a1
  666.         cmp.w    (a1),d0        ;is this previous preset ??
  667.         beq.s    nochgpres    ;yes...no need to change
  668.         move.w    d0,(a1)        ;save preset to prevmidicpres
  669.         subq.w    #1,d0        ;sub 1 to get 0 - 127
  670.         btst    #6,inst_midich(a3)
  671.         bne.s    hmn_extpreset
  672. ; -------- PREPARE PRESET CHANGE COMMAND ---------------------------------
  673. hmn_ordpreset    lea    preschgdata+1-DB(a6),a0
  674.         move.b    d0,(a0)        ;push the number to second byte
  675.         moveq    #2,d0
  676. hmn_sendpreset    move.b    #$c0,-(a0)    ;command: $C
  677.         or.b    d5,(a0)        ;"or" midi channel
  678.         move.w    d1,-(sp)
  679.         bsr.w    _AddMIDId
  680.         move.w    (sp)+,d1
  681.         tst.b    d2
  682.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  683.  
  684. ; -------- PREPARE & SEND NOTE ON COMMAND --------------------------------
  685. nochgpres    lea    bytesinnotebuff-DB(a6),a0
  686.         movea.l    a0,a1
  687.         adda.w    (a0)+,a0
  688.         or.b    #$90,d5        ;MIDI: Note on
  689.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  690.         move.b    d1,(a0)+    ;MIDI msg note #
  691.         move.b    d2,(a0)        ;MIDI msg volume
  692.         beq.s    hmn_suppress    ;vol = 0 -> no note
  693.         addq.w    #3,(a1)
  694.         rts
  695. hmn_suppress    st    trk_prevmidin(a5)
  696.         rts
  697.  
  698. ; -------- HANDLE EXTENDED PRESET ----------------------------------------
  699. hmn_extpreset    cmp.w    #100,d0
  700.         blt.s    hmn_ordpreset
  701.         moveq    #99,d3
  702. hmn_loop100    sub.w    #100,d0
  703.         addq.b    #1,d3
  704.         cmp.w    #100,d0
  705.         bge.s    hmn_loop100
  706.         lea    preschgdata+2-DB(a6),a0
  707.         move.b    d0,(a0)        ;push the <= 99 number
  708.         move.b    d3,-(a0)    ;push the >= 100 number
  709.         moveq    #3,d0
  710.         bra.s    hmn_sendpreset
  711.     ENDC
  712.  
  713.     IFNE    SYNTH
  714. ; -------- TRIGGER SYNTH NOTE, CLEAR PARAMETERS --------------------------
  715. handleSynthnote    move.b    d1,trk_prevnote2(a5)
  716.         move.l    a0,trk_synthptr(a5)
  717.         cmp.w    #-2,4(a0)    ;HYBRID??
  718.         bne.s    hSn_nossn
  719.         st    trk_synthtype(a5)
  720.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  721.         bra.w    tlwtst0        ;go and play it
  722. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  723.         lea    _periodtable+32-DB(a6),a1
  724.         move.b    trk_finetune(a5),d0    ;finetune value
  725.         add.b    d0,d0
  726.         add.b    d0,d0        ;multiple by 4...
  727.         ext.w    d0        ;extend
  728.         movea.l    0(a1,d0.w),a1    ;period table address
  729.         suba.w    #48,a1
  730.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  731.         add.w    d1,d1
  732.         move.w    0(a1,d1.w),d1
  733.         move.w    d1,trk_prevper(a5)
  734.         clr.l    trk_sampleptr(a5)
  735. hSn2:        lea    trk_arpgoffs(a5),a1
  736.         clr.l    (a1)+
  737.         clr.l    (a1)+
  738.         btst    #0,trk_miscflags(a5)
  739.         bne.s    hSn_cmdE ;cmd E given, don't clear trk_wfcmd!
  740.         clr.w    (a1)
  741. hSn_cmdE    addq.l    #2,a1
  742.         clr.w    (a1)+
  743.         clr.l    (a1)+
  744.         clr.l    (a1)+
  745.         clr.l    (a1)+
  746.         move.l    #sinetable,(a1)+
  747.         clr.w    (a1)+
  748.         movea.l    trk_synthptr(a5),a0
  749.                 move.w    18(a0),(a1)+
  750.                 clr.b    (a1)
  751.         moveq    #64,d4
  752.         rts
  753.  
  754. synth_start    move.w    trk_prevper(a5),d5
  755. synth_start2    move.l    a3,-(sp)    ;d0 = SynthPtr
  756.         move.l    d0,a0
  757.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  758. ; -------- SYNTHSOUND VOLUME SEQUENCE HANDLING ---------------------------
  759.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  760.         bgt.w    synth_wftbl        ;not 0...go to waveform
  761.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  762.         move.b    trk_volchgspd(a5),d0    ;volume change??
  763.         beq.s    synth_nochgvol        ;no.
  764.         add.b    trk_synvol(a5),d0    ;add previous volume
  765.         bpl.s    synth_voln2l        ;not negative
  766.         moveq    #0,d0            ;was negative => 0
  767. synth_voln2l    cmp.b    #$40,d0            ;too high??
  768.         ble.s    synth_voln2h        ;not 2 high.
  769.         moveq    #$40,d0            ;was 2 high => 64
  770. synth_voln2h    move.b    d0,trk_synvol(a5)    ;remember new...
  771. synth_nochgvol    move.l    trk_envptr(a5),d1    ;envelope pointer
  772.         beq.s    synth_novolenv
  773.         movea.l    d1,a1
  774.         move.b    (a1)+,d0
  775.         add.b    #128,d0
  776.         lsr.b    #2,d0
  777.         move.b    d0,trk_synvol(a5)
  778.         addq.b    #1,trk_envcount(a5)
  779.         bpl.s    synth_endenv
  780.         clr.b    trk_envcount(a5)
  781.         move.l    trk_envrestart(a5),a1
  782. synth_endenv    move.l    a1,trk_envptr(a5)
  783. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  784.         tst.b    trk_volwait(a5)        ;WAI(t) active
  785.         beq.s    synth_getvolcmd        ;no
  786.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  787.         ble.s    synth_getvolcmd        ;0 => continue
  788.         bra.w    synth_wftbl        ;> 0 => still wait
  789. synth_inccnt    addq.b    #1,d0
  790. synth_getvolcmd    addq.b    #1,d0            ;advance pointer
  791.         move.b    21(a0,d0.w),d1        ;get command
  792.         bmi.s    synth_cmd        ;negative = command
  793.         move.b    d1,trk_synvol(a5)    ;set synthvol
  794.         bra.w    synth_endvol        ;end of volume executing
  795. synth_cmd    and.w    #$000f,d1
  796.         add.b    d1,d1
  797.         move.w    synth_vtbl(pc,d1.w),d1
  798.         jmp    syv(pc,d1.w)
  799. synth_vtbl    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  800.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  801.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  802.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  803.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  804. ; -------- VOLUME SEQUENCE COMMANDS --------------------------------------
  805. syv
  806. syv_fe        move.b    22(a0,d0.w),d0        ;JMP
  807.         bra.s    synth_getvolcmd
  808. syv_f0        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  809.         bra.s    synth_inccnt
  810. syv_f1        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  811.         addq.b    #1,d0
  812.         bra.s    synth_endvol
  813. syv_f3        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  814.         bra.s    synth_inccnt
  815. syv_f2        move.b    22(a0,d0.w),d1
  816.         neg.b    d1
  817.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  818.         bra.s    synth_inccnt
  819. syv_fa        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  820.         clr.b    trk_wfwait(a5)
  821.         bra.s    synth_inccnt
  822. syv_f4        move.b    22(a0,d0.w),d1
  823.         bsr.s    synth_getwf
  824.         clr.l    trk_envrestart(a5)
  825. syv_f4end    move.l    a1,trk_envptr(a5)
  826.         clr.b    trk_envcount(a5)
  827.         bra.w    synth_inccnt
  828. syv_f5        move.b    22(a0,d0.w),d1
  829.         bsr.s    synth_getwf
  830.         move.l    a1,trk_envrestart(a5)
  831.         bra.s    syv_f4end
  832. syv_f6        clr.l    trk_envptr(a5)
  833.         bra.w    synth_getvolcmd
  834. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  835.         add.w    d1,d1    ;create index
  836.         add.w    d1,d1
  837.         lea    278(a0),a1
  838.         adda.w    d1,a1
  839.         movea.l    (a1),a1        ;get wform address
  840.         addq.l    #2,a1        ;skip length
  841.         rts
  842. syv_ff        subq.b    #1,d0
  843. synth_endvol    move.w    d0,trk_volcmd(a5)
  844. synth_wftbl    move.b    trk_synvol(a5),trk_prevvol(a5)
  845.         adda.w    #158,a0
  846. ; -------- SYNTHSOUND WAVEFORM SEQUENCE HANDLING -------------------------
  847.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  848.         bgt.w    synth_arpeggio        ;not yet...
  849.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  850.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  851.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  852.         beq.s    synth_tstwfwai        ;0 = no change
  853. wytanwet    add.w    trk_perchg(a5),d1    ;add value to current change
  854.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  855. synth_tstwfwai    tst.b    trk_wfwait(a5)        ;WAI ??
  856.         beq.s    synth_getwfcmd        ;not waiting...
  857.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  858.         beq.s    synth_getwfcmd        ;waiting finished
  859.         bra.w    synth_arpeggio        ;still sleep...
  860. synth_incwfc    addq.b    #1,d0
  861. synth_getwfcmd    addq.b    #1,d0            ;advance position counter
  862.         move.b    -9(a0,d0.w),d1        ;get command
  863.         bmi.s    synth_wfcmd        ;negative = command
  864.         ext.w    d1
  865.         add.w    d1,d1
  866.         add.w    d1,d1
  867.         movea.l    120(a0,d1.w),a1
  868.         move.w    (a1)+,ac_len(a3)    ;push waveform length
  869.         move.l    a1,ac_ptr(a3)        ;and the new pointer
  870.         bra.w    synth_wfend        ;no new commands now...
  871. synth_wfcmd    and.w    #$000f,d1        ;get the right nibble
  872.         add.b    d1,d1            ;* 2
  873.         move.w    synth_wfctbl(pc,d1.w),d1
  874.         jmp    syw(pc,d1.w)        ;jump to command
  875. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  876.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  877.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  878.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  879. ; -------- WAVEFORM SEQUENCE COMMANDS ------------------------------------
  880. syw
  881. syw_f7        move.b    -8(a0,d0.w),d1
  882.         ext.w    d1
  883.         add.w    d1,d1
  884.         add.w    d1,d1
  885.         movea.l    120(a0,d1.w),a1
  886.         addq.l    #2,a1
  887.         move.l    a1,trk_synvibwf(a5)
  888.         bra.s    synth_incwfc
  889. syw_fe        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  890.         bra.s    synth_getwfcmd
  891. syw_fc        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  892.         move.w    d0,trk_arpgoffs(a5)
  893. synth_findare    addq.b    #1,d0
  894.         tst.b    -9(a0,d0.w)
  895.         bpl.s    synth_findare
  896.         bra.s    synth_getwfcmd
  897. syw_f0        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  898.         bra    synth_incwfc
  899. syw_f1        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  900.         addq.b    #1,d0
  901.         bra.s    synth_wfend
  902. syw_f4        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  903.         bra.w    synth_incwfc
  904. syw_f5        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  905.         addq.b    #1,trk_synthvibspd+1(a5)
  906.         bra.w    synth_incwfc
  907. syw_f2        moveq    #0,d1            ;set slide down
  908.         move.b    -8(a0,d0.w),d1
  909. synth_setsld    move.w    d1,trk_wfchgspd(a5)
  910.         bra.w    synth_incwfc
  911. syw_f3        move.b    -8(a0,d0.w),d1        ;set slide up
  912.         neg.b    d1
  913.         ext.w    d1
  914.         bra.s    synth_setsld
  915. syw_f6        clr.w    trk_perchg(a5)        ;reset period
  916.         move.w    trk_prevper(a5),d5
  917.         bra.w    synth_getwfcmd
  918. syw_fa        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  919.         clr.b    trk_volwait(a5)
  920.         bra.w    synth_incwfc
  921. syw_ff        subq.b    #1,d0        ;pointer = END - 1
  922. synth_wfend    move.w    d0,trk_wfcmd(a5)
  923. ; -------- HANDLE SYNTHSOUND ARPEGGIO ------------------------------------
  924. synth_arpeggio    move.w    trk_arpgoffs(a5),d0
  925.         beq.s    synth_vibrato
  926.         moveq    #0,d1
  927.         move.b    -8(a0,d0.w),d1
  928.         add.b    trk_prevnote2(a5),d1
  929.         movea.l    trk_periodtbl(a5),a1    ;get period table
  930.         add.w    d1,d1
  931.         move.w    0(a1,d1.w),d5
  932.         addq.b    #1,d0
  933.         tst.b    -8(a0,d0.w)
  934.         bpl.s    synth_noarpres
  935.         move.w    trk_arpsoffs(a5),d0
  936. synth_noarpres    move.w    d0,trk_arpgoffs(a5)
  937. ; -------- HANDLE SYNTHSOUND VIBRATO -------------------------------------
  938. synth_vibrato    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  939.         beq.s    synth_rts        ;0 => no vibrato
  940.         move.w    trk_synviboffs(a5),d0    ;get offset
  941.         lsr.w    #4,d0            ;/ 16
  942.         and.w    #$1f,d0            ;sinetable offset (0-31)
  943.         movea.l trk_synvibwf(a5),a0
  944.         move.b    0(a0,d0.w),d0       ;get a byte
  945.         ext.w    d0            ;to word
  946.         muls    d1,d0            ;amplify (* depth)
  947.         asr.w    #8,d0            ;and divide by 64
  948.         add.w    d0,d5            ;add vibrato...
  949.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  950.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  951. synth_rts    add.w    trk_perchg(a5),d5
  952.         cmp.w    #113,d5            ;overflow??
  953.         bge.s    synth_pern2h
  954.         moveq    #113,d1
  955. synth_pern2h    move.l    (sp)+,a3
  956.         rts
  957.     ENDC
  958. sinetable    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  959.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  960.         dc.b    -106,-90,-71,-49,-25,0
  961.  
  962. _IntHandler:    movem.l    d2-d7/a2-a6,-(sp)
  963.     IFNE    CIAB|VBLANK
  964.         movea.l    a1,a6    ;get data base address (int_Data)
  965.     ENDC
  966.     IFEQ    CIAB|VBLANK
  967.         lea    DB,a6    ;don't expect a1 to contain DB address
  968.     ENDC
  969.         tst.b    bpmcounter-DB(a6)
  970.         bmi.s    plr_nobpm
  971.         subq.b    #1,bpmcounter-DB(a6)
  972.         ble.s    plr_bpmcnt0
  973.         bra.w    plr_exit
  974. plr_bpmcnt0    move.b    #4,bpmcounter-DB(a6)
  975. plr_nobpm    movea.l    _module-DB(a6),a2
  976.         move.l    a2,d0
  977.         beq.w    plr_exit
  978.     IFNE    MIDI
  979.         clr.b    lastcmdbyte-DB(a6)    ;no MIDI optimization
  980.     ENDC
  981.         tst.w    mmd_pstate(a2)
  982.         beq.w    plr_exit
  983.     IFNE    MIDI
  984.         clr.l    dmaonmsk-DB(a6)
  985.     ENDC
  986.     IFEQ    MIDI
  987.         clr.w    dmaonmsk-DB(a6)
  988.     ENDC
  989.         movea.l    mmd_songinfo(a2),a4
  990.         moveq    #0,d3
  991.         move.b    mmd_counter(a2),d3
  992.         addq.b    #1,d3
  993.         cmp.b    msng_tempo2(a4),d3
  994.         bge.s    plr_pnewnote    ;play new note
  995.         move.b    d3,mmd_counter(a2)
  996.         bne.w    nonewnote    ;do just fx
  997. ; --- new note!!
  998. plr_pnewnote:    clr.b    mmd_counter(a2)
  999.         tst.w    blkdelay-DB(a6)
  1000.         beq.s    plr_noblkdelay
  1001.         subq.w    #1,blkdelay-DB(a6)
  1002.         bne.w    nonewnote
  1003. ; --- now start to play it
  1004. ; -------- GET ADDRESS OF NOTE DATA --------------------------------------
  1005. plr_noblkdelay    move.w    mmd_pblock(a2),d0
  1006.         bsr.w    GetNoteDataAddr
  1007.         moveq    #0,d7        ;number of track
  1008.         moveq    #0,d4
  1009.     IFNE    PLAYMMD0
  1010.         cmp.b    #'1',3(a2)
  1011.         sge    d5        ;d5 set -> >= MMD1
  1012.     ENDC
  1013.         lea    trackdataptrs-DB(a6),a1
  1014. ; -------- TRACK LOOP (FOR EACH TRACK) -----------------------------------
  1015. plr_loop0:    movea.l    (a1)+,a5    ;get address of this track's struct
  1016. ; ---------------- get the note numbers
  1017.         moveq    #0,d3
  1018.     IFNE    PLAYMMD0
  1019.         tst.b    d5
  1020.         bne.s    plr_mmd1_1
  1021.         move.b    (a3)+,d0
  1022.         move.b    (a3),d3
  1023.         addq.l    #2,a3
  1024.         lsr.b    #4,d3
  1025.         bclr    #7,d0
  1026.         beq.s    plr_bseti4
  1027.         bset    #4,d3
  1028. plr_bseti4    bclr    #6,d0
  1029.         beq.s    plr_bseti5
  1030.         bset    #5,d3
  1031. plr_bseti5    move.b    d0,trk_currnote(a5)
  1032.         beq.s    plr_nngok
  1033.         move.b    d0,(a5)
  1034.         bra.s    plr_nngok
  1035. plr_mmd1_1
  1036.     ENDC
  1037.         move.b    (a3)+,d0    ;get the number of this note
  1038.         bpl.s    plr_nothinote
  1039.         moveq    #0,d0
  1040. plr_nothinote    move.b    d0,trk_currnote(a5)
  1041.         beq.s    plr_nosetprevn
  1042.         move.b    d0,(a5)
  1043. plr_nosetprevn    move.b    (a3),d3        ;instrument number
  1044.         addq.l    #3,a3        ;adv. to next track
  1045. ; ---------------- check if there's an instrument number
  1046. plr_nngok    and.w    #$3F,d3
  1047.         beq.s    noinstnum
  1048. ; ---------------- finally, save the number
  1049.         subq.b    #1,d3
  1050.         move.b    d3,trk_previnstr(a5) ;remember instr. number!
  1051. ; ---------------- get the pointer of data's of this sample in Song-struct
  1052.         move.w    d3,d0
  1053.         asl.w    #3,d3
  1054.         lea    0(a4,d3.w),a0    ;a0 contains now address of it
  1055.         move.l    a0,trk_previnstra(a5)
  1056. ; ---------------- get volume
  1057.         move.b    inst_svol(a0),trk_prevvol(a5) ;vol of this instr
  1058.         move.b    inst_strans(a0),trk_stransp(a5)
  1059. ; ---------------- remember some values of this instrument
  1060.         lea    holdvals-DB(a6),a0
  1061.         adda.w    d0,a0
  1062.     IFNE    HOLD
  1063.         move.b    (a0),trk_inithold(a5)        ;hold
  1064.         move.b    63(a0),trk_initdecay(a5)    ;decay
  1065.     ENDC
  1066.         move.b    2*63(a0),trk_finetune(a5)    ;finetune
  1067.         move.b    6*63(a0),trk_outputdev(a5)    ;output dev
  1068. ; ---------------- remember transpose
  1069.         clr.w    trk_soffset(a5)        ;sample offset
  1070.         clr.b    trk_miscflags(a5)    ;misc.
  1071. noinstnum    addq.w    #1,d7
  1072.         cmp.w    numtracks-DB(a6),d7
  1073.         blt    plr_loop0
  1074.         bsr.w    DoPreFXLoop
  1075. ; -------- NOTE PLAYING LOOP ---------------------------------------------
  1076.         moveq    #0,d7
  1077.         lea    trackdataptrs-DB(a6),a1
  1078. plr_loop2    movea.l    (a1)+,a5
  1079.         tst.b    trk_fxtype(a5)
  1080.         bne.s    plr_loop2_end
  1081.         move.b    trk_currnote(a5),d1
  1082.         beq.s    plr_loop2_end
  1083. ; ---------------- play
  1084.         move.l    a1,-(sp)
  1085.         ext.w    d1
  1086.         moveq    #0,d3
  1087.         move.b    trk_previnstr(a5),d3    ;instr #
  1088.         movea.l    trk_previnstra(a5),a3    ;instr data address
  1089.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1090.         bne.s    plr_nohold0        ;not 0 -> OK
  1091.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1092. ; ---------------- and finally:
  1093. plr_nohold0    bsr    _PlayNote        ;play it
  1094.         move.l    (sp)+,a1
  1095. plr_loop2_end    addq.w    #1,d7
  1096.         cmp.w    numtracks-DB(a6),d7
  1097.         blt.s    plr_loop2
  1098. ; -------- THE REST... ---------------------------------------------------
  1099.         bsr.s    AdvSngPtr
  1100. nonewnote    bsr.w    DoFX
  1101. plr_endfx:    bsr    _StartDMA    ;turn on DMA
  1102. plr_exit:    movem.l    (sp)+,d2-d7/a2-a6
  1103.     IFNE    VBLANK
  1104.         moveq    #0,d0
  1105.     ENDC
  1106.         rts
  1107.  
  1108. ; and advance song pointers
  1109. AdvSngPtr    move.l    mmd_pblock(a2),fxplineblk-DB(a6) ;store pline/block for fx
  1110.         move.w    nextblockline-DB(a6),d1
  1111.         beq.s    plr_advlinenum
  1112.         clr.w    nextblockline-DB(a6)
  1113.         subq.w    #1,d1
  1114.         bra.s    plr_linenumset
  1115. plr_advlinenum    move.w    mmd_pline(a2),d1    ;get current line #
  1116.         addq.w    #1,d1            ;advance line number
  1117. plr_linenumset    cmp.w    numlines-DB(a6),d1     ;advance block?
  1118.         bhi.s    plr_chgblock        ;yes.
  1119.         tst.b    nextblock-DB(a6)    ;command F00/1Dxx?
  1120.         beq.w    plr_nochgblock        ;no, don't change block
  1121. ; -------- CHANGE BLOCK? -------------------------------------------------
  1122. plr_chgblock    tst.b    nxtnoclrln-DB(a6)
  1123.         bne.s    plr_noclrln
  1124.         moveq    #0,d1            ;clear line number
  1125. plr_noclrln    tst.w    mmd_pstate(a2)        ;play block or play song
  1126.         bpl.w    plr_nonewseq        ;play block only...
  1127.         cmp.b    #'2',3(a2)        ;MMD2?
  1128.         bne.s    plr_noMMD2_0
  1129. ; ********* BELOW CODE FOR MMD2 ONLY ************************************
  1130. ; -------- CHANGE SEQUENCE -----------------------------------------------
  1131. plr_skipseq    move.w    mmd_pseq(a2),d0        ;actually stored as << 2
  1132.         movea.l    msng_pseqs(a4),a1    ;ptr to playseqs
  1133.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1134.         move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1135.         tst.b    nextblock-DB(a6)
  1136.         bmi.s    plr_noadvseq        ;Bxx sets nextblock to -1
  1137.         addq.w    #1,d0            ;advance sequence number
  1138. plr_noadvseq    cmp.w    40(a0),d0        ;is this the highest seq number??
  1139.         blt.s    plr_notagain        ;no.
  1140. ; -------- CHANGE SECTION ------------------------------------------------
  1141.         move.w    mmd_psecnum(a2),d0    ;get section number
  1142.         addq.w    #1,d0            ;increase..
  1143.         cmp.w    msng_songlen(a4),d0    ;highest section?
  1144.         blt.s    plr_nohisec
  1145.         moveq    #0,d0            ;yes.
  1146. plr_nohisec    move.w    d0,mmd_psecnum(a2)    ;push back.
  1147.         add.w    d0,d0
  1148.         movea.l    msng_sections(a4),a0    ;section table
  1149.         move.w    0(a0,d0.w),d0        ;new playseqlist number
  1150.         add.w    d0,d0
  1151.         add.w    d0,d0
  1152.         move.w    d0,mmd_pseq(a2)
  1153.         movea.l    0(a1,d0.w),a0        ;a0 = ptr to new PlaySeq
  1154.         moveq    #0,d0            ;playseq OFFSET = 0
  1155. ; -------- FETCH BLOCK NUMBER FROM SEQUENCE ------------------------------
  1156. plr_notagain    move.w    d0,mmd_pseqnum(a2)    ;remember new playseq pos
  1157.         add.w    d0,d0
  1158.         move.w    42(a0,d0.w),d0        ;get number of the block
  1159.         bpl.s    plr_changeblk    ;neg. values for future expansion
  1160.         bra.s    plr_skipseq    ;(skip them)
  1161. ; ********* BELOW CODE FOR MMD0/MMD1 ONLY *******************************
  1162. plr_noMMD2_0    move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1163.         tst.b    nextblock-DB(a6)
  1164.         bmi.s    plr_noadvseq_b        ;Bxx sets nextblock to -1
  1165.         addq.w    #1,d0            ;advance sequence number
  1166. plr_noadvseq_b    cmp.w    msng_songlen(a4),d0    ;is this the highest seq number??
  1167.         blt.s    plr_notagain_b        ;no.
  1168.         moveq    #0,d0            ;yes: restart song
  1169. plr_notagain_b    move.b    d0,mmd_pseqnum+1(a2)    ;remember new playseq-#
  1170.         lea    msng_playseq(a4),a0    ;offset of sequence table
  1171.         move.b    0(a0,d0.w),d0        ;get number of the block
  1172. ; ********* BELOW CODE FOR BOTH FORMATS *********************************
  1173. plr_changeblk
  1174.     IFNE    CHECK
  1175.         cmp.w    msng_numblocks(a4),d0    ;beyond last block??
  1176.         blt.s    plr_nolstblk        ;no..
  1177.         moveq    #0,d0            ;play block 0
  1178.     ENDC
  1179. plr_nolstblk    move.w    d0,mmd_pblock(a2)    ;store block number
  1180. plr_nonewseq    clr.w    nextblock-DB(a6)     ;clear this if F00 set it
  1181. ; ------------------------------------------------------------------------
  1182. plr_nochgblock    move.w    d1,mmd_pline(a2)    ;set new line number
  1183.  
  1184.     IFNE    HOLD
  1185.         lea    trackdataptrs-DB(a6),a5
  1186.         move.w    mmd_pblock(a2),d0    ;pblock
  1187.         bsr.w    GetBlockAddr
  1188.         move.w    mmd_pline(a2),d0    ;play line
  1189.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  1190.     IFNE    PLAYMMD0
  1191.         cmp.b    #'1',3(a2)
  1192.         bge.s    plr_mmd1_2
  1193.         move.b    (a0),d7            ;# of tracks
  1194.         move.w    d0,d1
  1195.         add.w    d0,d0    ;d0 * 2
  1196.         add.w    d1,d0    ;+ d0 = d0 * 3
  1197.         mulu    d7,d0
  1198.         lea    2(a0,d0.w),a3
  1199.         subq.b    #1,d7
  1200. plr_chkholdb    movea.l    (a5)+,a1        ;track data
  1201.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1202.         bmi.s    plr_holdendb        ;no.
  1203.         move.b    (a3),d1            ;get the 1st byte..
  1204.         bne.s    plr_hold1b
  1205.         move.b    1(a3),d1
  1206.         and.b    #$f0,d1
  1207.         beq.s    plr_holdendb        ;don't hold
  1208.         bra.s    plr_hold2b
  1209. plr_hold1b    and.b    #$3f,d1            ;note??
  1210.         beq.s    plr_hold2b        ;no, cont hold..
  1211.         move.b    1(a3),d1
  1212.         and.b    #$0f,d1            ;get cmd
  1213.         subq.b    #3,d1            ;is there command 3 (slide)
  1214.         bne.s    plr_holdendb        ;no -> end holding
  1215. plr_hold2b    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1216. plr_holdendb    addq.l    #3,a3        ;next note
  1217.         dbf    d7,plr_chkholdb
  1218.         rts
  1219. plr_mmd1_2
  1220.     ENDC
  1221.         move.w    (a0),d7        ;# of tracks
  1222.         add.w    d0,d0
  1223.         add.w    d0,d0        ;d0 = d0 * 4
  1224.         mulu    d7,d0
  1225.         lea    8(a0,d0.l),a3
  1226.         subq.b    #1,d7
  1227. plr_chkhold    movea.l    (a5)+,a1        ;track data
  1228.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1229.         bmi.s    plr_holdend        ;no.
  1230.         move.b    (a3),d1            ;get the 1st byte..
  1231.         bne.s    plr_hold1
  1232.         move.b    1(a3),d0
  1233.         and.b    #$3F,d0
  1234.         beq.s    plr_holdend        ;don't hold
  1235.         bra.s    plr_hold2
  1236. plr_hold1    and.b    #$7f,d1            ;note??
  1237.         beq.s    plr_hold2        ;no, cont hold..
  1238.         move.b    2(a3),d1
  1239.         subq.b    #3,d1            ;is there command 3 (slide)
  1240.         bne.s    plr_holdend        ;no -> end holding
  1241. plr_hold2    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1242. plr_holdend    addq.l    #4,a3        ;next note
  1243.         dbf    d7,plr_chkhold
  1244.     ENDC
  1245.         rts
  1246.  
  1247. ; *******************************************************************
  1248. ; DoPreFXLoop:    Loop and call DoPreFX
  1249. ; *******************************************************************
  1250. DoPreFXLoop:
  1251. ; -------- PRE-FX COMMAND HANDLING LOOP ----------------------------------
  1252.         moveq    #0,d5    ;command page count
  1253. plr_loop1    move.w    mmd_pblock(a2),d0
  1254.         bsr.w    GetBlockAddr
  1255.         move.w    d5,d1
  1256.         move.w    mmd_pline(a2),d2
  1257.         bsr.w    GetCmdPointer
  1258.         movea.l    a0,a3
  1259.         moveq    #0,d7    ;clear track count
  1260.         lea    trackdataptrs-DB(a6),a1
  1261. plr_loop1_1    movea.l    (a1)+,a5
  1262.         clr.b    trk_fxtype(a5)
  1263.         move.b    (a3),d0            ;command #
  1264.         beq.s    plr_loop1_end
  1265.         moveq    #0,d4
  1266.         move.b    1(a3),d4        ;data byte
  1267.     IFNE    PLAYMMD0
  1268.         cmp.b    #3,d6            ;if adv == 3 -> MMD0
  1269.         bne.s    doprefx_mmd12mask
  1270.         and.w    #$0F,d0
  1271.         bra.s    doprefx_mmd0maskd
  1272. doprefx_mmd12mask
  1273.     ENDC
  1274.         and.w    #$1F,d0
  1275. doprefx_mmd0maskd
  1276.         bsr.s    DoPreFX
  1277.         or.b    d0,trk_fxtype(a5)
  1278. plr_loop1_end    adda.w    d6,a3            ;next track...
  1279.         addq.w    #1,d7
  1280.         cmp.w    numtracks-DB(a6),d7
  1281.         blt.s    plr_loop1_1
  1282.         addq.w    #1,d5
  1283.         cmp.w    numpages-DB(a6),d5
  1284.         bls.s    plr_loop1
  1285.         rts
  1286.  
  1287. ; *******************************************************************
  1288. ; DoPreFX: Perform effects that must be handled before note playing
  1289. ; *******************************************************************
  1290. ; args:        a6 = DB            d0 = command number (w)
  1291. ;        a5 = track data        d5 = note number
  1292. ;        a4 = song        d4 = data
  1293. ;                    d7 = track #
  1294. ; returns:    d0 = 0: play - d0 = 1: don't play
  1295.  
  1296. rtplay        MACRO
  1297.         moveq    #0,d0
  1298.         rts
  1299.         ENDM
  1300. rtnoplay    MACRO
  1301.         moveq    #1,d0
  1302.         rts
  1303.         ENDM
  1304.  
  1305. DoPreFX:    add.b    d0,d0    ;* 2
  1306.         move.w    f_table(pc,d0.w),d0
  1307.         jmp    fst(pc,d0.w)
  1308. f_table        dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1309.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  1310.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  1311.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,f_1e-fst,f_1f-fst
  1312. fst
  1313. ; ---------------- tempo (F)
  1314. f_0f        tst.b    d4        ;test effect qual..
  1315.         beq    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  1316.         cmp.b    #$f0,d4        ;..is zero, go to next block
  1317.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  1318. ; ---------------- just an ordinary "change tempo"-request
  1319.     IFNE    CIAB
  1320.         moveq    #0,d0        ;will happen!!!
  1321.         move.b    d4,d0
  1322.         bsr    _SetTempo    ;change The Tempo
  1323.     ENDC
  1324. fx        rtplay
  1325. ; ---------------- no, it was FFx, something special will happen!!
  1326. fx0fspecial:    cmp.b    #$f2,d4
  1327.         beq.s    f_1f
  1328.         cmp.b    #$f4,d4
  1329.         beq.s    f_1f
  1330.         cmp.b    #$f5,d4
  1331.         bne.s    isfxfe
  1332. ; ---------------- FF2 (or 1Fxx)
  1333. f_1f
  1334.     IFNE    HOLD
  1335.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1336.         bne.s    f_1frts            ;not 0 -> OK
  1337.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1338.     ENDC
  1339. f_1frts        rtnoplay
  1340. isfxfe:        cmp.b    #$fe,d4
  1341.         bne.s    notcmdfe
  1342. ; ---------------- it was FFE, stop playing
  1343.         clr.w    mmd_pstate(a2)
  1344.     IFNE    CIAB
  1345.         movea.l    craddr-DB(a6),a0
  1346.         bclr    #0,(a0)
  1347.     ENDC
  1348.         bsr.w    SoundOff
  1349.     IFNE    AURA
  1350.         jsr    _RemAura(pc)
  1351.     ENDC
  1352.         adda.w    #8,sp    ;2 subroutine levels
  1353.         bra.w    plr_exit
  1354. f_ffe_no8    rtplay
  1355. notcmdfe:    cmp.b    #$fd,d4 ;change period
  1356.         bne.s    isfxff
  1357. ; ---------------- FFD, change the period, don't replay the note
  1358.     IFNE    CHECK
  1359.         cmp.w    #4,d7 ;no tracks above 4, thank you!!
  1360.         bge.s    f_ff_rts
  1361.     ENDC
  1362.         move.l    trk_periodtbl(a5),d1    ;period table
  1363.         beq.s    f_1frts
  1364.         movea.l    d1,a0
  1365.         move.b    trk_currnote(a5),d0
  1366.         subq.b    #1,d0    ;sub 1 to make "real" note number
  1367.     IFNE    CHECK
  1368.         bmi.s    f_1frts
  1369.     ENDC
  1370.         add.b    msng_playtransp(a4),d0
  1371.         add.b    trk_stransp(a5),d0
  1372.         add.w    d0,d0
  1373.         bmi.s    f_1frts
  1374.         move.w    0(a0,d0.w),trk_prevper(a5) ;get & push the period
  1375.         rtnoplay
  1376. isfxff:        cmp.b    #$ff,d4        ;note off??
  1377.         bne.s    f_ff_rts
  1378.         move.w    d7,d0
  1379.         move.l    a1,-(sp)
  1380.         bsr.w    _ChannelOff
  1381.         move.l    (sp)+,a1
  1382. f_ff_rts    rtplay
  1383. ; ---------------- F00, called Pattern Break in ST
  1384. fx0fchgblck:    move.b    #1,nextblock-DB(a6) ;next block????...YES!!!! (F00)
  1385.         bra.s    f_ff_rts
  1386. ; ---------------- was not Fxx, then it's something else!!
  1387. f_0e
  1388.     IFNE    CHECK
  1389.         cmp.b    #4,d7
  1390.         bge.s    f_0e_rts
  1391.     ENDC
  1392.         bset    #0,trk_miscflags(a5)
  1393.         move.b    d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  1394. f_0e_rts    rtplay
  1395. ; ---------------- change volume
  1396. f_0c        move.b    d4,d0
  1397.         bpl.s    plr_nosetdefvol
  1398.         and.b    #$7F,d0
  1399.     IFNE    CHECK
  1400.         cmp.b    #64,d0
  1401.         bgt.s    go_nocmd
  1402.     ENDC
  1403.         moveq    #0,d1
  1404.         move.b    trk_previnstr(a5),d1
  1405.         asl.w    #3,d1
  1406.         move.b    d0,inst_svol(a4,d1.w)    ;set new svol
  1407.         bra.s    plr_setvol
  1408. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  1409.         bne.s    volhex
  1410.         lsr.b    #4,d0        ;get number from left
  1411.         mulu    #10,d0        ;number of tens
  1412.         move.b    d4,d1        ;get again
  1413.         and.b    #$0f,d1        ;this time don't get tens
  1414.         add.b    d1,d0        ;add them
  1415. volhex:
  1416.     IFNE    CHECK
  1417.         cmp.b    #64,d0
  1418.         bhi.s    go_nocmd
  1419.     ENDC
  1420. plr_setvol    move.b    d0,trk_prevvol(a5)
  1421. go_nocmd    rtplay
  1422. ; ---------------- tempo2 change??
  1423. f_09
  1424.     IFNE    CHECK
  1425.         and.b    #$1F,d4
  1426.         bne.s    fx9chk
  1427.         moveq    #$20,d4
  1428.     ENDC
  1429. fx9chk:        move.b    d4,msng_tempo2(a4)
  1430. f_09_rts    rtplay
  1431. ; ---------------- block delay
  1432. f_1e        tst.w    blkdelay-DB(a6)
  1433.         bne.s    f_1e_rts
  1434.         addq.w    #1,d4
  1435.         move.w    d4,blkdelay-DB(a6)
  1436. f_1e_rts    rtplay
  1437. ; ---------------- finetune
  1438. f_15
  1439.     IFNE    CHECK
  1440.         cmp.b    #7,d4
  1441.         bgt.s    f_15_rts
  1442.         cmp.b    #-8,d4
  1443.         blt.s    f_15_rts
  1444.     ENDC
  1445.         move.b    d4,trk_finetune(a5)
  1446. f_15_rts    rtplay
  1447. ; ---------------- repeat loop
  1448. f_16        tst.b    d4
  1449.         bne.s    plr_dorpt
  1450.         move.w    mmd_pline(a2),rptline-DB(a6)
  1451.         bra.s    f_16_rts
  1452. plr_dorpt    tst.w    rptcounter-DB(a6)
  1453.         beq.s    plr_newrpt
  1454.         subq.w    #1,rptcounter-DB(a6)
  1455.         beq.s    f_16_rts
  1456.         bra.s    plr_setrptline
  1457. plr_newrpt    move.b    d4,rptcounter+1-DB(a6)
  1458. plr_setrptline    move.w    rptline-DB(a6),d0
  1459.         addq.w    #1,d0
  1460.         move.w    d0,nextblockline-DB(a6)
  1461. f_16_rts    rtplay
  1462. ; ---------------- preset change
  1463. f_1c        cmp.b    #$80,d4
  1464.         bhi.s    f_1c_rts
  1465.         moveq    #0,d1
  1466.         move.b    trk_previnstr(a5),d1
  1467.         add.w    d1,d1
  1468.         lea    ext_midipsets-DB(a6),a0
  1469.         ext.w    d4
  1470.         move.w    d4,0(a0,d1.w)        ;set MIDI preset
  1471. f_1c_rts    rtplay
  1472. ; ---------------- note off time set??
  1473. f_08
  1474.     IFNE    HOLD
  1475.         move.b    d4,d0
  1476.         lsr.b    #4,d4        ;extract left  nibble
  1477.         and.b    #$0f,d0        ; "   "  right  "  "
  1478.         move.b    d4,trk_initdecay(a5)    ;left = decay
  1479.         move.b    d0,trk_inithold(a5)    ;right = hold
  1480.     ENDC
  1481.         rtplay
  1482. ; ---------------- sample begin offset
  1483. f_19        lsl.w    #8,d4
  1484.         move.w    d4,trk_soffset(a5)
  1485. f_19_rts    rtplay
  1486. ; ---------------- cmd Bxx, "position jump"
  1487. f_0b
  1488.     IFNE    CHECK
  1489.         cmp.b    #'2',3(a2)
  1490.         beq.s    chk0b_mmd2
  1491.         cmp.w    msng_songlen(a4),d4
  1492.         bhi.s    f_0b_rts
  1493.         bra.s    chk0b_end
  1494. chk0b_mmd2    move.w    mmd_pseq(a2),d0        ;get seq number
  1495.         movea.l    msng_pseqs(a4),a0    ;ptr to playseqs
  1496.         movea.l    0(a0,d0.w),a0        ;a0 = ptr to curr PlaySeq
  1497.         cmp.w    40(a0),d4        ;test song length
  1498.         bhi.s    f_0b_rts
  1499. chk0b_end
  1500.     ENDC
  1501.         move.w    d4,mmd_pseqnum(a2)
  1502.         st    nextblock-DB(a6)    ; = 1
  1503. f_0b_rts    rtplay
  1504. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1505. f_1d        move.w    #$1ff,nextblock-DB(a6)
  1506.         addq.w    #1,d4
  1507.         move.w    d4,nextblockline-DB(a6)
  1508.         rtplay
  1509. ; ---------------- try portamento (3)
  1510. f_03
  1511.     IFNE    CHECK
  1512.         cmp.w    #4,d7
  1513.         bge.s    f_03_rts
  1514.     ENDC
  1515.         moveq    #0,d0
  1516.         move.b    trk_currnote(a5),d0
  1517.         subq.b    #1,d0        ;subtract note number
  1518.         bmi.s    plr_setfx3spd    ;0 -> set new speed
  1519.         move.l    trk_periodtbl(a5),d1
  1520.         beq.s    f_03_rts
  1521.         movea.l    d1,a0
  1522.         add.b    msng_playtransp(a4),d0    ;play transpose
  1523.         add.b    trk_stransp(a5),d0 ;and instrument transpose
  1524.         bmi.s    f_03_rts    ;again.. too low
  1525.         add.w    d0,d0
  1526.         move.w    0(a0,d0.w),trk_porttrgper(a5) ;period of this note is the target
  1527. plr_setfx3spd:    tst.b    d4        ;qual??
  1528.         beq.s    f_03_rts    ;0 -> do nothing
  1529.         move.b    d4,trk_prevportspd(a5)    ;store speed
  1530. f_03_rts    rtnoplay
  1531.  
  1532. ; *******************************************************************
  1533. ; DoFX: Handle effects, hold/fade etc.
  1534. ; *******************************************************************
  1535. DoFX        moveq    #0,d3
  1536.         move.b    mmd_counter(a2),d3
  1537.     IFNE    HOLD
  1538.         lea    trackdataptrs-DB(a6),a1
  1539. ; Loop 1: Hold/Fade handling
  1540.         moveq    #0,d7    ;clear track count
  1541. dofx_loop1    movea.l    (a1)+,a5
  1542.         bsr.w    HoldAndFade
  1543.         addq.w    #1,d7
  1544.         cmp.w    numtracks-DB(a6),d7
  1545.         blt.s    dofx_loop1
  1546.     ENDC
  1547. ; Loop 2: Track command handling
  1548.         moveq    #0,d5    ;command page count
  1549. dofx_loop2    move.w    fxplineblk-DB(a6),d0
  1550.         bsr.w    GetBlockAddr
  1551.         movea.l    a0,a3
  1552.     IFNE    PLAYMMD0
  1553.         cmp.b    #'1',3(a2)
  1554.         bge.s    dofx_sbd_nommd0
  1555.         bsr.w    StoreBlkDimsMMD0
  1556.         bra.s    dofx_sbd_mmd0
  1557. dofx_sbd_nommd0
  1558.     ENDC
  1559.         bsr.w    StoreBlockDims
  1560. dofx_sbd_mmd0    move.w    d5,d1
  1561.         move.w    fxplineblk+2-DB(a6),d2
  1562.         movea.l    a3,a0
  1563.         bsr.s    GetCmdPointer
  1564.         movea.l    a0,a3
  1565.         moveq    #0,d7    ;clear track count
  1566.         lea    trackdataptrs-DB(a6),a1
  1567. dofx_loop2_1    movea.l    (a1)+,a5
  1568.         moveq    #0,d4
  1569.         move.b    (a3),d0            ;command #
  1570.         move.b    1(a3),d4        ;data byte
  1571.     IFNE    PLAYMMD0
  1572.         cmp.b    #3,d6            ;if adv == 3 -> MMD0
  1573.         bne.s    dofx_mmd12mask
  1574.         and.w    #$0F,d0
  1575.         bra.s    dofx_mmd0maskd
  1576. dofx_mmd12mask
  1577.     ENDC
  1578.         and.w    #$1F,d0
  1579. dofx_mmd0maskd    tst.b    trk_fxtype(a5)
  1580.         bgt.s    dofx_lend2_1    ;1 = skip
  1581.     IFNE    MIDI
  1582.         beq.s    dofx_chfx
  1583.         bsr.w    MIDIFX
  1584.         bra.s    dofx_lend2_1
  1585.     ENDC
  1586.     IFEQ    MIDI
  1587.         bne.s    dofx_lend2_1
  1588.     ENDC
  1589. dofx_chfx    bsr.w    ChannelFX
  1590. dofx_lend2_1    adda.w    d6,a3            ;next track...
  1591.         addq.w    #1,d7
  1592.         cmp.w    numtracks-DB(a6),d7
  1593.         blt.s    dofx_loop2_1
  1594.         addq.w    #1,d5
  1595.         cmp.w    numpages-DB(a6),d5
  1596.         bls.s    dofx_loop2
  1597. ; Loop 3: Updating audio hardware
  1598.         moveq    #0,d7    ;clear track count
  1599.         lea    trackdataptrs-DB(a6),a1
  1600. dofx_loop3    movea.l    (a1)+,a5
  1601.     IFNE    HOLD
  1602.         tst.b    trk_fxtype(a5)
  1603.         bne.s    dofx_lend3    ;only in case 0 (norm)
  1604.     ENDC
  1605.     IFEQ    HOLD
  1606.         cmp.w    #4,d7
  1607.         bge.s    dofx_stopl3
  1608.     ENDC
  1609.         bsr.w    UpdatePerVol
  1610. dofx_lend3    addq.w    #1,d7
  1611.         cmp.w    numtracks-DB(a6),d7
  1612.         blt.s    dofx_loop3
  1613. dofx_stopl3    rts
  1614.  
  1615. ; *******************************************************************
  1616. ; GetCmdPointer: Return command pointer for track 0
  1617. ; *******************************************************************
  1618. ; args:        a0 = block pointer
  1619. ;        d1 = page number
  1620. ;        d2 = line number
  1621. ;        a2 = module
  1622. ; result:    a0 = command pointer (i.e. trk 0 note + 2)
  1623. ;        d6 = track advance (bytes)
  1624. ; scratches:    d0, d1, d2, a0
  1625. ; Note: no num_pages check! If numpages > 0 it can be assumed that
  1626. ; extra pages exist.
  1627.  
  1628. GetCmdPointer
  1629.     IFNE    PLAYMMD0
  1630.         cmp.b    #'1',3(a2)
  1631.         blt.s    GetCmdPtrMMD0
  1632.     ENDC
  1633.         mulu    (a0),d2        ;d2 = line # * numtracks
  1634.         add.l    d2,d2        ;d2 *= 2...
  1635.         subq.w    #1,d1
  1636.         bmi.s    gcp_page0
  1637.         movea.l    4(a0),a0
  1638.         movea.l    12(a0),a0
  1639.         add.w    d1,d1
  1640.         add.w    d1,d1
  1641.         movea.l    4(a0,d1.w),a0    ;command data
  1642.         adda.l    d2,a0
  1643.         moveq    #2,d6
  1644.         rts
  1645. gcp_page0    add.l    d2,d2        ;d2 *= 4
  1646.         lea    10(a0,d2.l),a0    ;offs: 4 = header, 2 = note
  1647.         moveq    #4,d6        ;track advance (bytes)
  1648.         rts
  1649.     IFNE    PLAYMMD0
  1650. GetCmdPtrMMD0    moveq    #0,d0
  1651.         move.b    (a0),d0        ;get numtracks
  1652.         mulu    d0,d2        ;line # * numtracks
  1653.         move.w    d2,d0
  1654.         add.w    d2,d2
  1655.         add.w    d0,d2        ; *= 3...
  1656.         lea    3(a0,d2.l),a0    ;offs: 2 = header, 1 = note
  1657.         moveq    #3,d6
  1658.         rts
  1659.     ENDC
  1660.  
  1661. ; *******************************************************************
  1662. ; GetBlockAddr: Return pointer to block
  1663. ; *******************************************************************
  1664. ; args:        d0 = block number
  1665. ; result:    a0 = block pointer
  1666. ; scratches: d0, a0
  1667.  
  1668. GetBlockAddr    movea.l    mmd_blockarr(a2),a0
  1669.         add.w    d0,d0
  1670.         add.w    d0,d0
  1671.         movea.l    0(a0,d0.w),a0
  1672.         rts
  1673.  
  1674. ; *******************************************************************
  1675. ; GetNoteDataAddr: Check & return addr. of current note
  1676. ; *******************************************************************
  1677. ;args:        d0 = pblock        a6 = DB
  1678. ;returns:    a3 = address
  1679. ;scratches:    d0, a0, d1
  1680.  
  1681. GetNoteDataAddr    bsr.w    GetBlockAddr
  1682.         movea.l    a0,a3
  1683.     IFNE    PLAYMMD0
  1684.         cmp.b    #'1',3(a2)
  1685.         blt.s    GetNDAddrMMD0
  1686.     ENDC
  1687.         bsr.w    StoreBlockDims
  1688.         move.w    numlines-DB(a6),d1
  1689.         move.w    mmd_pline(a2),d0
  1690.         cmp.w    d1,d0        ;check if block end exceeded...
  1691.         bls.s    plr_nolinex
  1692.         move.w    d1,d0
  1693. plr_nolinex    add.w    d0,d0
  1694.         add.w    d0,d0    ;d0 = d0 * 4
  1695.         mulu    numtracks-DB(a6),d0
  1696.         lea    8(a3,d0.l),a3    ;address of current note
  1697.         rts
  1698.  
  1699.     IFNE    PLAYMMD0
  1700. GetNDAddrMMD0    bsr.w    StoreBlkDimsMMD0
  1701.         move.w    numlines-DB(a6),d1
  1702.         move.w    mmd_pline(a2),d0
  1703.         cmp.w    d1,d0        ;check if block end exceeded...
  1704.         bls.s    plr_nolinex2
  1705.         move.w    d1,d0
  1706. plr_nolinex2    move.w    d0,d1
  1707.         add.w    d0,d0
  1708.         add.w    d1,d0    ;d0 = d0 * 3
  1709.         mulu    numtracks-DB(a6),d0
  1710.         lea    2(a3,d0.l),a3    ;address of current note
  1711.         rts
  1712.     ENDC
  1713.  
  1714. ; *******************************************************************
  1715. ; StoreBlockDims: Store block dimensions
  1716. ; *******************************************************************
  1717. ; args:        a0 = block ptr, a6 = DB
  1718.  
  1719. StoreBlockDims    move.l    (a0)+,numtracks-DB(a6)    ;numtracks & lines
  1720.         tst.l    (a0)            :BlockInfo
  1721.         beq.s    sbd_1page
  1722.         movea.l    (a0),a0
  1723.         move.l    12(a0),d0        ;BlockInfo.pagetable
  1724.         beq.s    sbd_1page
  1725.         movea.l    d0,a0
  1726.         move.w    (a0),numpages-DB(a6)    ;num_pages
  1727.         rts
  1728. sbd_1page    clr.w    numpages-DB(a6)
  1729.         rts
  1730.  
  1731.     IFNE    PLAYMMD0
  1732. StoreBlkDimsMMD0
  1733.         clr.w    numpages-DB(a6)
  1734.         moveq    #0,d0
  1735.         move.b    (a0)+,d0        ;numtracks
  1736.         move.w    d0,numtracks-DB(a6)
  1737.         move.b    (a0),d0            ;numlines
  1738.         move.w    d0,numlines-DB(a6)
  1739.         rts
  1740.     ENDC
  1741.  
  1742. ; *******************************************************************
  1743. ; HoldAndFade: Handle hold/fade
  1744. ; *******************************************************************
  1745. ; args:        a5 = track data
  1746. ;        a6 = DB
  1747. ;        d7 = track #
  1748. ; scratches:    d0, d1, a0
  1749.  
  1750.     IFNE    HOLD
  1751. HoldAndFade
  1752.     IFNE    MIDI
  1753.         tst.b    trk_prevmidin(a5)    ;is it MIDI??
  1754.         bne.w    plr_haf_midi
  1755.     ENDC
  1756.     IFNE    CHECK
  1757.         cmp.w    #4,d7
  1758.         bge.w    plr_haf_midi    ;no non-MIDI effects in tracks 4 - 15
  1759.     ENDC
  1760.         tst.b    trk_noteoffcnt(a5)
  1761.         bmi.s    plr_haf_noholdexp
  1762.         subq.b    #1,trk_noteoffcnt(a5)
  1763.         bpl.s    plr_haf_noholdexp
  1764.     IFNE    SYNTH
  1765.         tst.b    trk_synthtype(a5)        ;synth/hybrid??
  1766.         beq.s    plr_nosyndec
  1767.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1768.         clr.b    trk_volwait(a5)            ;abort WAI
  1769.         bra.s    plr_haf_noholdexp
  1770.     ENDC
  1771. plr_nosyndec    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1772.         bne.s    plr_haf_noholdexp        ;if > 0, don't stop sound
  1773.         moveq    #0,d0
  1774.         bset    d7,d0
  1775.         move.w    d0,$dff096            ;shut DMA...
  1776. plr_haf_noholdexp
  1777.         move.b    trk_fadespd(a5),d0    ;fade??
  1778.         beq.s    plr_haf_dofx        ;no.
  1779.         sub.b    d0,trk_prevvol(a5)
  1780.         bpl.s    plr_nofade2low
  1781.         clr.b    trk_prevvol(a5)
  1782.         clr.b    trk_fadespd(a5)        ;fade no more
  1783. plr_nofade2low
  1784. plr_haf_dofx    clr.b    trk_fxtype(a5)
  1785. plr_haf_rts    rts
  1786. ; MIDI version
  1787. plr_haf_midi
  1788.     IFNE    MIDI
  1789.         st    trk_fxtype(a5)
  1790.         tst.b    trk_noteoffcnt(a5)
  1791.         bmi.s    plr_haf_rts
  1792.         subq.b    #1,trk_noteoffcnt(a5)
  1793.         bpl.s    plr_haf_rts
  1794.         move.b    trk_prevmidin(a5),d1
  1795.         beq.s    plr_haf_rts
  1796.         lea    noteondata-DB(a6),a0
  1797.         exg.l    a5,a1
  1798.         bsr.w    choff_midi
  1799.         exg.l    a5,a1
  1800.     ENDC
  1801.         rts
  1802. ;hold
  1803.     ENDC
  1804.  
  1805. ; *******************************************************************
  1806. ; ChannelFX:    Do an effect on a channel
  1807. ; *******************************************************************
  1808. ;args:                    d3 = counter
  1809. ;        a4 = song struct    d4 = command qual (long, byte used)
  1810. ;        a5 = track data ptr    
  1811. ;        a6 = DB            d0 = command (long, byte used)
  1812. ;                    d7 = track (channel) number
  1813. ;scratches: d0, d1, d4, a0
  1814.  
  1815. ChannelFX    add.b    d0,d0    ;* 2
  1816.         move.w    fx_table(pc,d0.w),d0
  1817.         jmp    fxs(pc,d0.w)
  1818. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1819.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1820.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_0c-fxs,fx_0d-fxs,fx_xx-fxs
  1821.         dc.w    fx_0f-fxs
  1822.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1823.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1824.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1825.         dc.w    fx_1f-fxs
  1826. fxs:
  1827. ;    **************************************** Effect 01 ******
  1828. fx_01        tst.b    d3
  1829.         bne.s    fx_01nocnt0
  1830.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1831.         bne.s    fx_01rts
  1832. fx_01nocnt0    move.w    trk_prevper(a5),d0
  1833.         sub.w    d4,d0
  1834.         cmp.w    #113,d0
  1835.         bge.s    fx_01noovf
  1836.         move.w    #113,d0
  1837. fx_01noovf    move.w    d0,trk_prevper(a5)
  1838. fx_xx        ;fx_xx is just a RTS
  1839. fx_01rts    rts
  1840. ;    **************************************** Effect 11 ******
  1841. fx_11        tst.b    d3
  1842.         bne.s    fx_11rts
  1843.         sub.w    d4,trk_prevper(a5)
  1844. fx_11rts    rts
  1845. ;    **************************************** Effect 02 ******
  1846. fx_02        tst.b    d3
  1847.         bne.s    fx_02nocnt0
  1848.         btst    #5,msng_flags(a4)
  1849.         bne.s    fx_02rts
  1850. fx_02nocnt0    add.w    d4,trk_prevper(a5)
  1851. fx_02rts    rts
  1852. ;    **************************************** Effect 12 ******
  1853. fx_12        tst.b    d3
  1854.         bne.s    fx_12rts
  1855.         add.w    d4,trk_prevper(a5)
  1856. fx_12rts    rts
  1857. ;    **************************************** Effect 00 ******
  1858. fx_00        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1859.         beq.s    fx_00rts
  1860.         move.l    d3,d0
  1861.         divu    #3,d0
  1862.         swap    d0
  1863.         subq.b    #1,d0
  1864.         bgt.s    fx_arp2
  1865.         blt.s    fx_arp0
  1866.         and.b    #$0f,d4
  1867.         bra.s    fx_doarp
  1868. fx_arp0        lsr.b    #4,d4
  1869.         bra.s    fx_doarp
  1870. fx_arp2        moveq    #0,d4
  1871. fx_doarp:    move.b    (a5),d0
  1872.         subq.b    #1,d0        ;-1 to make it 0 - 127
  1873.         add.b    msng_playtransp(a4),d0    ;add play transpose
  1874.         add.b    trk_stransp(a5),d0    ;add instrument transpose
  1875.         add.b    d0,d4
  1876.         move.l    trk_periodtbl(a5),d1
  1877.         beq.s    fx_00rts
  1878.         movea.l    d1,a0
  1879.         add.b    d0,d0
  1880.         move.w    0(a0,d0.w),d0    ;base note period
  1881.         add.b    d4,d4
  1882.         sub.w    0(a0,d4.w),d0    ;calc difference from base note
  1883.         move.w    d0,trk_arpadjust(a5)
  1884. fx_00rts    rts
  1885. ;    **************************************** Effect 04 ******
  1886. fx_14        move.b    #6,trk_vibshift(a5)
  1887.         bra.s    vib_cont
  1888. fx_04        move.b    #5,trk_vibshift(a5)
  1889. vib_cont    tst.b    d3
  1890.         bne.s    nonvib
  1891.         move.b    d4,d1
  1892.         beq.s    nonvib
  1893.         and.w    #$0f,d1
  1894.         beq.s    plr_chgvibspd
  1895.         move.w    d1,trk_vibrsz(a5)
  1896. plr_chgvibspd    and.b    #$f0,d4
  1897.         beq.s    nonvib
  1898.         lsr.b    #3,d4
  1899.         and.b    #$3e,d4
  1900.         move.b    d4,trk_vibrspd(a5)
  1901. nonvib        move.b    trk_vibroffs(a5),d0
  1902.         lsr.b    #2,d0
  1903.         and.w    #$1f,d0
  1904.         moveq    #0,d1
  1905.         lea    sinetable(pc),a0
  1906.         move.b    0(a0,d0.w),d0
  1907.         ext.w    d0
  1908.         muls    trk_vibrsz(a5),d0
  1909.         move.b    trk_vibshift(a5),d1
  1910.         asr.w    d1,d0
  1911.         move.w    d0,trk_vibradjust(a5)
  1912.         move.b    trk_vibrspd(a5),d0
  1913.         add.b    d0,trk_vibroffs(a5)
  1914. fx_04rts    rts
  1915. ;    **************************************** Effect 06 ******
  1916. fx_06:        tst.b    d3
  1917.         bne.s    fx_06nocnt0
  1918.         btst    #5,msng_flags(a4)
  1919.         bne.s    fx_04rts
  1920. fx_06nocnt0    bsr.s    plr_volslide        ;Volume slide
  1921.         bra.s    nonvib            ;+ Vibrato
  1922. ;    **************************************** Effect 07 ******
  1923. fx_07        tst.b    d3
  1924.         bne.s    nontre
  1925.         move.b    d4,d1
  1926.         beq.s    nontre
  1927.         and.w    #$0f,d1
  1928.         beq.s    plr_chgtrespd
  1929.         move.w    d1,trk_tremsz(a5)
  1930. plr_chgtrespd    and.b    #$f0,d4
  1931.         beq.s    nontre
  1932.         lsr.b    #2,d4
  1933.         and.b    #$3e,d4
  1934.         move.b    d4,trk_tremspd(a5)
  1935. nontre        move.b    trk_tremoffs(a5),d0
  1936.         lsr.b    #3,d0
  1937.         and.w    #$1f,d0
  1938.         lea    sinetable(pc),a0
  1939.         move.b    0(a0,d0.w),d1
  1940.         ext.w    d1
  1941.         muls    trk_tremsz(a5),d1
  1942.         asr.w    #7,d1
  1943.         move.b    trk_tremspd(a5),d0
  1944.         add.b    d0,trk_tremoffs(a5)
  1945.         add.b    trk_prevvol(a5),d1
  1946.         bpl.s    tre_pos
  1947.         moveq    #0,d1
  1948. tre_pos        cmp.b    #64,d1
  1949.         ble.s    tre_no2hi
  1950.         moveq    #64,d1
  1951. tre_no2hi    move.b    d1,trk_tempvol(a5)
  1952.         rts
  1953. ;    ********* VOLUME SLIDE FUNCTION *************************
  1954. plr_volslide    move.b    d4,d0
  1955.         moveq    #0,d1
  1956.         move.b    trk_prevvol(a5),d1 ;move previous vol to d1
  1957.         and.b    #$f0,d0
  1958.         bne.s    crescendo
  1959.         sub.b    d4,d1    ;sub from prev. vol
  1960. voltest0    bpl.s    novolover64
  1961.         moveq    #0,d1    ;volumes under zero not accepted
  1962.         bra.s    novolover64
  1963. crescendo:    lsr.b    #4,d0
  1964.         add.b    d0,d1
  1965. voltest        cmp.b    #64,d1
  1966.         ble.s    novolover64
  1967.         moveq    #64,d1
  1968. novolover64    move.b    d1,trk_prevvol(a5)
  1969. volsl_rts    rts
  1970. ;    **************************************** Effect 0D/0A ***
  1971. fx_0a:
  1972. fx_0d:        tst.b    d3
  1973.         bne.s    plr_volslide
  1974.         btst    #5,msng_flags(a4)
  1975.         beq.s    plr_volslide
  1976.         rts
  1977. ;    **************************************** Effect 05 ******
  1978. fx_05:        tst.b    d3
  1979.         bne.s    fx_05nocnt0
  1980.         btst    #5,msng_flags(a4)
  1981.         bne.s    fx_05rts
  1982. fx_05nocnt0    bsr.s    plr_volslide
  1983.         bra.s    fx_03nocnt0
  1984. fx_05rts    rts
  1985. ;    **************************************** Effect 1A ******
  1986. fx_1a        tst.b    d3
  1987.         bne.s    volsl_rts
  1988.         move.b    trk_prevvol(a5),d1
  1989.         add.b    d4,d1
  1990.         bra.s    voltest
  1991. ;    **************************************** Effect 1B ******
  1992. fx_1b        tst.b    d3
  1993.         bne.s    volsl_rts
  1994.         move.b    trk_prevvol(a5),d1
  1995.         sub.b    d4,d1
  1996.         bra.s    voltest0
  1997. ;    **************************************** Effect 03 ******
  1998. fx_03        tst.b    d3
  1999.         bne.s    fx_03nocnt0
  2000.         btst    #5,msng_flags(a4)
  2001.         bne.s    fx_03rts
  2002. fx_03nocnt0    move.w    trk_porttrgper(a5),d0    ;d0 = target period
  2003.         beq.s    fx_03rts
  2004.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  2005.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  2006.         cmp.w    d0,d1
  2007.         bhi.s    subper    ;curr. period > target period
  2008.         add.w    d4,d1    ;add the period
  2009.         cmp.w    d0,d1
  2010.         bge.s    targreached
  2011.         bra.s    targnreach
  2012. subper:        sub.w    d4,d1    ;subtract
  2013.         cmp.w    d0,d1    ;compare current period to target period
  2014.         bgt.s    targnreach
  2015. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  2016.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  2017. targnreach:    move.w    d1,trk_prevper(a5)
  2018. fx_03rts    rts
  2019. ;    **************************************** Effect 13 ******
  2020. fx_13:        cmp.b    #3,d3
  2021.         bge.s    fx_13rts    ;if counter < 3
  2022.         neg.w    d4
  2023.         move.w    d4,trk_vibradjust(a5)    ;subtract effect qual...
  2024. fx_13rts    rts
  2025. ;    *********************************************************
  2026. fx_0c:        tst.b    d3
  2027.         bne.s    fx_13rts
  2028. dvc_0        move.b    trk_prevvol(a5),d1
  2029.         rts
  2030. ;    **************************************** Effect 10 ******
  2031. fx_10:
  2032.     IFNE    MIDI
  2033.         tst.b    d3
  2034.         bne.s    fx_13rts
  2035.         move.w    d4,d0
  2036.         bra.w    _InitMIDIDump
  2037.     ENDC
  2038.     IFEQ    MIDI
  2039.         rts
  2040.     ENDC
  2041. ;    **************************************** Effect 18 ******
  2042. fx_18        cmp.b    d4,d3
  2043.         bne.s    fx_18rts
  2044.         clr.b    trk_prevvol(a5)
  2045. fx_18rts    rts
  2046. ;    **************************************** Effect 1F ******
  2047. fx_1f        move.b    d4,d1
  2048.         lsr.b    #4,d4        ;note delay
  2049.         beq.s    nonotedelay
  2050.         cmp.b    d4,d3        ;compare to counter
  2051.         blt.s    fx_18rts    ;tick not reached
  2052.         bne.s    nonotedelay
  2053.         bra    playfxnote    ;trigger note
  2054. nonotedelay    and.w    #$0f,d1        ;retrig?
  2055.         beq.s    fx_18rts
  2056.         moveq    #0,d0
  2057.         move.b    d3,d0
  2058.         divu    d1,d0
  2059.         swap    d0        ;get modulo of counter/tick
  2060.         tst.w    d0
  2061.         bne.s    fx_18rts
  2062.         bra    playfxnote    ;retrigger
  2063. ;    **************************************** Effect 0F ******
  2064. ;    see below...
  2065. ;    *********************************************************
  2066.  
  2067. ; *******************************************************************
  2068. ; UpdatePerVol:    Update audio registers (period & volume) after FX
  2069. ; *******************************************************************
  2070. ; args:        a6 = DB            d7 = channel #
  2071. ;        a5 = track data
  2072. ; scratches:    d0, d1, a0, d5
  2073. UpdatePerVol    move.w    trk_prevper(a5),d5
  2074.     IFNE    SYNTH
  2075.         move.l    trk_synthptr(a5),d0
  2076.         beq.s    plr_upv_nosynth
  2077.         move.l    a1,-(sp)
  2078.         bsr.w    synth_start
  2079.         move.l    (sp)+,a1
  2080.     ENDC
  2081. plr_upv_nosynth    add.w    trk_vibradjust(a5),d5
  2082.         sub.w    trk_arpadjust(a5),d5
  2083.         clr.l    trk_vibradjust(a5)    ;clr both adjusts
  2084.         movea.l    trk_audioaddr(a5),a0
  2085.         move.w    d5,ac_per(a0)        ;push period
  2086.         moveq    #0,d0
  2087.         move.b    trk_tempvol(a5),d0
  2088.         bpl.s    plr_upv_setvol
  2089.         move.b    trk_prevvol(a5),d0
  2090. plr_upv_setvol    st    trk_tempvol(a5)
  2091. ; -------- GetRelVol: Calculate track volume -----------------------------
  2092. ; track # = d7, note vol = d0, song = a4
  2093.     IFNE    RELVOL
  2094.         mulu    trk_trackvol(a5),d0    ;d0 = master v. * track v. * volume
  2095.         lsr.w    #8,d0
  2096.     ENDC
  2097.         move.b    d0,ac_vol+1(a0)
  2098.         rts
  2099.  
  2100. ; **** a separate routine for handling command 0F
  2101. fx_0f        cmp.b    #$f1,d4
  2102.         bne.s    no0ff1
  2103.         cmp.b    #3,d3
  2104.         beq.s    playfxnote
  2105.         rts
  2106. no0ff1:        cmp.b    #$f2,d4
  2107.         bne.s    no0ff2
  2108.         cmp.b    #3,d3
  2109.         beq.s    playfxnote
  2110.         rts
  2111. no0ff2:        cmp.b    #$f3,d4
  2112.         bne.s    no0ff3
  2113.         move.b    d3,d0
  2114.         beq.s    cF_rts
  2115.         and.b    #1,d0        ;is 2 or 4
  2116.         bne.s    cF_rts
  2117. playfxnote:    moveq    #0,d1
  2118.         move.b    trk_currnote(a5),d1    ;get note # of curr. note
  2119.         beq.s    cF_rts
  2120.         move.b    trk_noteoffcnt(a5),d0    ;get hold counter
  2121.         bmi.s    pfxn_nohold        ;no hold, or hold over
  2122.         add.b    d3,d0            ;increase by counter val
  2123.         bra.s    pfxn_hold
  2124. pfxn_nohold    move.b    trk_inithold(a5),d0    ;get initial hold
  2125.         bne.s    pfxn_hold
  2126.         st    d0
  2127. pfxn_hold    move.b    d0,trk_noteoffcnt(a5)
  2128.         movem.l    a1/a3/d3/d6,-(sp)
  2129.         moveq    #0,d3
  2130.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  2131.         movea.l    trk_previnstra(a5),a3
  2132.         bsr    _PlayNote
  2133. pndone_0ff    movem.l    (sp)+,a1/a3/d3/d6
  2134. cF_rts        rts
  2135. no0ff3:        cmp.b    #$f4,d4        ;triplet cmd 1
  2136.         bne.s    no0ff4
  2137.         moveq    #0,d0
  2138.         move.b    msng_tempo2(a4),d0
  2139.         divu    #3,d0
  2140.         cmp.b    d0,d3
  2141.         beq.s    playfxnote
  2142.         rts
  2143. no0ff4        cmp.b    #$f5,d4        ;triplet cmd 2
  2144.         bne.s    no0ff5
  2145.         moveq    #0,d0
  2146.         move.b    msng_tempo2(a4),d0
  2147.         divu    #3,d0
  2148.         add.w    d0,d0
  2149.         cmp.b    d0,d3
  2150.         beq.s    playfxnote
  2151.         rts
  2152. no0ff5        cmp.b    #$f8,d4        ;f8 = filter off
  2153.         beq.s    plr_filteroff
  2154.         cmp.b    #$f9,d4        ;f9 = filter on
  2155.         bne.s    cF_rts
  2156.         bclr    #1,$bfe001
  2157.         bset    #0,msng_flags(a4)
  2158.         rts
  2159. plr_filteroff:    bset    #1,$bfe001
  2160.         bclr    #0,msng_flags(a4)
  2161.         rts
  2162.  
  2163. ; -------- HANDLE DMA WAIT (PROCESSOR-INDEPENDENT) -----------------------
  2164. _Wait1line:    move.w    d0,-(sp)
  2165. wl0:        move.b    $dff007,d0
  2166. wl1:        cmp.b    $dff007,d0
  2167.         beq.s    wl1
  2168.         dbf    d1,wl0
  2169.         move.w    (sp)+,d0
  2170.         rts
  2171. pushnewvals:    movea.l    (a1)+,a5
  2172.         lsr.b    #1,d0
  2173.         bcc.s    rpnewv
  2174.         move.l    trk_sampleptr(a5),d1
  2175.         beq.s    rpnewv
  2176.         movea.l    trk_audioaddr(a5),a0
  2177.         move.l    d1,ac_ptr(a0)
  2178.         move.w    trk_samplelen(a5),ac_len(a0)
  2179. rpnewv:        rts
  2180.  
  2181. ; -------- AUDIO DMA ROUTINE ---------------------------------------------
  2182. _StartDMA:    ;This small routine turns on audio DMA
  2183.         move.w    dmaonmsk-DB(a6),d0    ;dmaonmsk contains the mask of
  2184.         beq.s    sdma_nodmaon    ;the channels that must be turned on
  2185.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  2186.         moveq    #80,d1
  2187. ; The following line makes the playroutine one scanline slower. If your
  2188. ; song works well without the following instruction, you can leave it out.
  2189.     IFNE    SYNTH
  2190.         add.w    d1,d1    ;sometimes double wait time is required
  2191.     ENDC
  2192.         bsr.s    _Wait1line
  2193.         move.w    d0,$dff096    ;do that!!!
  2194.         moveq    #80,d1
  2195.         bsr.s    _Wait1line
  2196.         lea    trackdataptrs-DB(a6),a1
  2197.         bsr.s    pushnewvals
  2198.         bsr.s    pushnewvals
  2199.         bsr.s    pushnewvals
  2200.     IFNE    MIDI
  2201.         bsr.s    pushnewvals
  2202.     ENDC
  2203.     IFEQ    MIDI
  2204.         bra.s    pushnewvals
  2205.     ENDC
  2206. sdma_nodmaon
  2207.     IFNE    MIDI
  2208.         lea    bytesinnotebuff-DB(a6),a0
  2209.         move.w    (a0)+,d0
  2210.         beq.s    rpnewv
  2211.         bra.w    _AddMIDId
  2212.     ENDC
  2213.         rts
  2214.  
  2215. _SetTempo:
  2216.     IFNE    CIAB
  2217.         move.l    _module-DB(a6),d1
  2218.         beq.s    ST_x
  2219.         move.l    d1,a0
  2220.         movea.l    mmd_songinfo(a0),a0
  2221.         btst    #5,msng_flags2(a0)
  2222.         bne.s    ST_bpm
  2223.         cmp.w    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  2224.         bhi.s    calctempo
  2225.         subq.b    #1,d0
  2226.         add.w    d0,d0
  2227.         move.w    sttempo+2(pc,d0.w),d1
  2228.         bra.s    pushtempo
  2229. calctempo:    move.l    timerdiv-DB(a6),d1
  2230.         divu    d0,d1
  2231. pushtempo:    movea.l    craddr+4-DB(a6),a0
  2232.         move.b    d1,(a0)        ;and set the CIA timer
  2233.         lsr.w    #8,d1
  2234.         movea.l    craddr+8-DB(a6),a0
  2235.         move.b    d1,(a0)
  2236.     ENDC
  2237. ST_x        rts ;   vv-- These values are the SoundTracker tempos (approx.)
  2238. sttempo:    dc.w    $0f00
  2239.     IFNE    CIAB
  2240.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  2241. ST_bpm        move.b    msng_flags2(a0),d1
  2242.         and.w    #$1F,d1
  2243.         addq.b    #1,d1
  2244.         mulu    d1,d0
  2245.         move.l    bpmdiv-DB(a6),d1
  2246.         divu    d0,d1
  2247.         bra.s    pushtempo
  2248.     ENDC
  2249.  
  2250.     IFNE    MIDI
  2251. MIDIFX        add.b    d0,d0    ;* 2
  2252.         move.w    midicmd_table(pc,d0.w),d0
  2253.         jmp    midifx(pc,d0.w)
  2254. midicmd_table    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  2255.         dc.w    mfx_05-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2256.         dc.w    mfx_0a-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_0d-midifx,mfx_0e-midifx
  2257.         dc.w    mfx_0f-midifx
  2258.         dc.w    mfx_10-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_13-midifx
  2259.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_17-midifx
  2260.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx
  2261.         dc.w    mfx_rts-midifx,mfx_rts-midifx,mfx_rts-midifx,mfx_1f-midifx
  2262. midifx        
  2263. mfx_01        lea    prevmidipbend-DB(a6),a0
  2264.         moveq    #0,d1
  2265.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  2266.         add.b    d1,d1        ;UWORD index
  2267.         tst.b    d4        ;x100??
  2268.         beq.s    resetpbend
  2269.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  2270.         lsl.w    #3,d4        ;multiply bend value by 8
  2271.         add.w    d4,d0
  2272.         cmp.w    #$3fff,d0
  2273.         bls.s    bendpitch
  2274.         move.w    #$3fff,d0
  2275. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  2276.         lsr.b    #1,d1        ;back to UBYTE
  2277.         or.b    #$e0,d1
  2278.         lea    noteondata-DB(a6),a0
  2279.         move.b    d1,(a0)        ;midi command & channel
  2280.         move.b    d0,1(a0)    ;lower value
  2281.         and.b    #$7f,1(a0)    ;clear bit 7
  2282.         lsr.w    #7,d0
  2283.         and.b    #$7f,d0        ;clr bit 7
  2284.         move.b    d0,2(a0)    ;higher 7 bits
  2285.         moveq    #3,d0
  2286.         bra.w    _AddMIDId
  2287.  
  2288. mfx_02        lea    prevmidipbend-DB(a6),a0
  2289.         moveq    #0,d1
  2290.         move.b    trk_prevmidich(a5),d1
  2291.         add.b    d1,d1
  2292.         tst.b    d4
  2293.         beq.s    resetpbend    ;x200??
  2294.         move.w    0(a0,d1.w),d0
  2295.         lsl.w    #3,d4
  2296.         sub.w    d4,d0
  2297.         bpl.s    bendpitch    ;not under 0
  2298.         moveq    #0,d0
  2299.         bra.s    bendpitch
  2300. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  2301.         bne.s    mfx_rts
  2302.         move.w    #$2000,d0
  2303.         bra.s    bendpitch
  2304. mfx_rts        rts
  2305. mfx_13
  2306. mfx_03        tst.b    d3
  2307.         bne.s    mfx_rts
  2308.         lea    prevmidipbend-DB(a6),a0
  2309.         moveq    #0,d1
  2310.         move.b    trk_prevmidich(a5),d1
  2311.         add.b    d1,d1
  2312.         move.b    d4,d0
  2313.         add.b    #128,d0
  2314.         lsl.w    #6,d0
  2315.         bra.s    bendpitch
  2316.  
  2317. mfx_0d        tst.b    d3
  2318.         bne.s    mfx_rts
  2319.         lea    noteondata+1-DB(a6),a0    ;CHANNEL AFTERTOUCH
  2320.         move.b    d4,(a0)    ;value
  2321.         bmi.s    mfx_rts
  2322.         move.b    trk_prevmidich(a5),-(a0)
  2323.         or.b    #$d0,(a0)
  2324.         moveq    #2,d0
  2325.         bra.w    _AddMIDId
  2326.  
  2327. mfx_0a        tst.b    d3
  2328.         bne.s    mfx_rts
  2329.         lea    noteondata+2-DB(a6),a0    ;POLYPHONIC AFTERTOUCH
  2330.         and.b    #$7f,d4
  2331.         move.b    d4,(a0)
  2332.         move.b    trk_prevmidin(a5),-(a0)
  2333.         ble.s    mfx_rts
  2334.         move.b    trk_prevmidich(a5),-(a0)
  2335.         or.b    #$A0,(a0)
  2336.         moveq    #3,d0
  2337.         bra.w    _AddMIDId
  2338.  
  2339. mfx_17        moveq    #$07,d0        ;07 = VOLUME
  2340.         bra.s    pushctrldata
  2341.  
  2342. mfx_04        moveq    #$01,d0        ;01 = MODULATION WHEEL
  2343.         bra.s    pushctrldata
  2344.  
  2345. mfx_0e        moveq    #$0a,d0
  2346. pushctrldata    tst.b    d3        ;do it only once in a note
  2347.         bne.s    mfx_rts2    ;(when counter = 0)
  2348.         lea    noteondata+2-DB(a6),a0 ;push "control change" data,
  2349.         move.b    d4,(a0)        ;second databyte
  2350.         bmi.s    mfx_rts2    ;$0 - $7F only
  2351.         move.b    d0,-(a0)    ;1st databyte
  2352.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  2353.         or.b    #$b0,(a0)    ;command (B)
  2354.         moveq    #3,d0
  2355.         bra.w    _AddMIDId
  2356.  
  2357. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  2358.         move.b    trk_prevmidich(a5),d6
  2359.         lea    midicontrnum-DB(a6),a0
  2360.         adda.w    d6,a0
  2361.         move.b    d4,(a0)
  2362. mfx_rts2    rts
  2363.  
  2364. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  2365.         bne.s    nomffa
  2366.         moveq    #$40,d0
  2367.         moveq    #$7f,d4
  2368.         bra.s    pushctrldata
  2369. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  2370.         bne.w    fx_0f
  2371.         moveq    #$40,d0
  2372.         moveq    #$00,d4
  2373.         bra.s    pushctrldata
  2374.  
  2375. mfx_00        tst.b    d4
  2376.         beq.s    mfx_rts2
  2377.         and.b    #$7f,d4
  2378.         move.b    trk_prevmidich(a5),d6
  2379.         lea    midicontrnum-DB(a6),a0
  2380.         move.b    0(a0,d6.w),d0
  2381.         bra.s    pushctrldata
  2382.  
  2383. mfx_10        tst.b    d3
  2384.         bne.s    mfx_rts3
  2385.         move.w    d4,d0
  2386.         bra.w    _InitMIDIDump
  2387.  
  2388. mfx_1f        move.b    d4,d1
  2389.         lsr.b    #4,d4        ;note delay
  2390.         beq.s    nonotedelay_m
  2391.         cmp.b    d4,d3        ;compare to counter
  2392.         blt.s    mfx_rts3    ;tick not reached
  2393.         bne.s    nonotedelay_m
  2394.         bsr    playfxnote    ;trigger note
  2395. nonotedelay_m    and.w    #$0f,d1        ;retrig?
  2396.         beq.s    mfx_rts3
  2397.         moveq    #0,d0
  2398.         move.b    d3,d0
  2399.         divu    d1,d0
  2400.         swap    d0        ;get modulo of counter/tick
  2401.         tst.w    d0
  2402.         beq    playfxnote
  2403. mfx_rts3    rts
  2404.  
  2405. _ResetMIDI:    movem.l    d2/a2/a6,-(sp)
  2406.         movea.l    4.w,a6        ;ExecBase
  2407.         jsr    -$78(a6)    ;Disable()
  2408.         lea    DB,a6
  2409. ; Clear preset memory
  2410.         lea    prevmidicpres-DB(a6),a0
  2411.         moveq    #7,d2
  2412. RM_loop0    clr.l    (a0)+    ;force presets to be set again
  2413.         dbf    d2,RM_loop0
  2414.         clr.b    lastcmdbyte
  2415. ; Reset pitchbenders & modulation wheels
  2416.         lea    midiresd-DB(a6),a2
  2417.         move.b    #$e0,(a2)
  2418.         move.b    #$b0,3(a2)
  2419.         moveq    #15,d2
  2420. respbendl:    movea.l    a2,a0
  2421.         moveq    #6,d0
  2422.         bsr.w    _AddMIDId
  2423.         addq.b    #1,(a2)
  2424.         addq.b    #1,3(a2)
  2425.         dbf    d2,respbendl
  2426.         lea    prevmidipbend-DB(a6),a2
  2427.         moveq    #15,d2
  2428. resprevpbends:    move.w    #$2000,(a2)+
  2429.         dbf    d2,resprevpbends
  2430. ; Clear dump variables
  2431.         clr.b    sysx-DB(a6)
  2432.         lea    dumpqueue-DB(a6),a0
  2433.         move.l    a0,dqreadptr-DB(a6)
  2434.         move.l    a0,dqwriteptr-DB(a6)
  2435.         clr.w    dqentries-DB(a6)
  2436. ; Enable & exit
  2437.         movea.l    4.w,a6
  2438.         jsr    -$7e(a6)    ;Enable()
  2439.         movem.l    (sp)+,d2/a2/a6
  2440.         rts
  2441.     ENDC
  2442.  
  2443. ; *************************************************************************
  2444. ; *************************************************************************
  2445. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2446. ; *************************************************************************
  2447. ; *************************************************************************
  2448.  
  2449.     IFEQ    EASY
  2450.         XDEF    _InitModule,_PlayModule
  2451.         XDEF    _InitPlayer,_RemPlayer,_StopPlayer
  2452.         XDEF    _ContModule
  2453.     ENDC
  2454.  
  2455. ; *************************************************************************
  2456. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  2457. ; *************************************************************************
  2458.  
  2459. _InitModule:    movem.l    a2-a3/d2,-(sp)
  2460.         move.l    a0,-(sp)
  2461.         beq    IM_exit            ;0 => xit
  2462.     IFNE    RELVOL
  2463.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  2464.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  2465.         ext.w    d0
  2466.         lea    trackdataptrs,a2
  2467.         cmp.b    #'2',3(a0)        ;MMD2?
  2468.         bne.s    IM_mmd01
  2469.         move.w    msng_numtracks(a1),d1
  2470.         subq.w    #1,d1
  2471.         movea.l    msng_trkvoltbl(a1),a1
  2472.         bra.s    IM_loop0
  2473. IM_mmd01    lea    msng_trkvol(a1),a1    ;a1 = trkvol
  2474.         moveq    #MAX_MMD1_TRACKS-1,d1
  2475. IM_loop0    move.b    (a1)+,d2    ;get vol...
  2476.         ext.w    d2
  2477.         move.l    (a2)+,a3    ;pointer to track data
  2478.         mulu    d0,d2        ;mastervol * trackvol
  2479.         lsr.w    #4,d2
  2480.         move.w    d2,trk_trackvol(a3)
  2481.         dbf    d1,IM_loop0
  2482.     ENDC
  2483.     IFNE    SYNTH
  2484.         lea    trackdataptrs,a2
  2485.         moveq    #3,d1
  2486. IM_loop1    move.l    (a2)+,a3
  2487.         clr.l    trk_synthptr(a3)
  2488.         clr.b    trk_synthtype(a3)
  2489.         dbf    d1,IM_loop1
  2490.     ENDC
  2491.         lea    holdvals,a2
  2492.         movea.l    a0,a3
  2493.         move.l    mmd_expdata(a0),d0    ;expdata...
  2494.     IFEQ    MIDI
  2495.         beq.s    IM_clrhlddec        ;none here
  2496.     ENDC
  2497.     IFNE    MIDI
  2498.         beq.w    IM_clrhlddec
  2499.     ENDC
  2500.         move.l    d0,a1
  2501.         move.l    4(a1),d0        ;exp_smp
  2502.     IFEQ    MIDI
  2503.         beq.s    IM_clrhlddec    ;again.. nothing
  2504.     ENDC
  2505.     IFNE    MIDI
  2506.         beq.w    IM_clrhlddec
  2507.     ENDC
  2508.         move.l    d0,a0        ;InstrExt...
  2509.         move.w    8(a1),d2    ;# of entries
  2510.     IFEQ    MIDI
  2511.         beq.s    IM_clrhlddec
  2512.     ENDC
  2513.     IFNE    MIDI
  2514.         beq.w    IM_clrhlddec
  2515.     ENDC
  2516.         subq.w    #1,d2        ;-1 (for dbf)
  2517.         move.w    10(a1),d0    ;entry size
  2518.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  2519.     IFNE    MIDI
  2520.         lea    4*63(a2),a1    ;pointer to ext_midipsets...
  2521.     ENDC
  2522. IM_loop2    clr.b    2*63(a2)        ;clear finetune
  2523.         cmp.w    #3,d0
  2524.         ble.s    IM_noftune
  2525.         move.b    3(a0),126(a2)    ;InstrExt.finetune -> finetune
  2526. IM_noftune    clr.b    3*63(a2)    ;clear flags
  2527.         cmp.w    #6,d0
  2528.         blt.s    IM_noflags
  2529.         move.b    5(a0),3*63(a2)    ;InstrExt.flags -> flags
  2530.         bra.s    IM_gotflags
  2531. IM_noflags    cmp.w    #1,inst_replen(a3)
  2532.         bls.s    IM_gotflags
  2533.         bset    #0,3*63(a2)
  2534. IM_gotflags    clr.b    6*63(a2)    ;Initally OUTPUT_STD
  2535.         cmp.w    #9,d0
  2536.         blt.s    IM_noopdev
  2537.         move.b    8(a0),6*63(a2)    ;get InstrExt.output_device
  2538.     IFNE    AURA
  2539.         cmp.b    #1,8(a0)    ;is it OUTPUT_AURA?
  2540.         bne.s    IM_noopdev
  2541. ; does no harm to call several times...
  2542.         jsr    _InitAura(pc)
  2543.     ENDC
  2544. IM_noopdev
  2545.     IFNE    MIDI
  2546.         cmp.w    #2,d0
  2547.         ble.s    IM_nsmnoff
  2548.         tst.b    2(a0)        ;suppress MIDI note off?
  2549.         beq.s    IM_nsmnoff
  2550.         bset    #7,inst_midich(a3)
  2551. IM_nsmnoff    move.b    inst_midipreset(a3),d1
  2552.         ext.w    d1
  2553.         move.w    d1,(a1)
  2554.         cmp.w    #8,d0
  2555.         ble.s    IM_nolongpset
  2556.         move.w    6(a0),(a1)    ;-> ext_midipsets
  2557.         btst    #1,5(a0)
  2558.         beq.s    IM_nolongpset
  2559.         bset    #6,inst_midich(a3)
  2560. IM_nolongpset    addq.l    #2,a1
  2561.     ENDC
  2562.         move.b    1(a0),63(a2)    ;InstrExt.decay -> decay
  2563.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  2564.         adda.w    d0,a0        ;ptr to next InstrExt
  2565.         addq.l    #8,a3        ;next instrument...
  2566.         dbf    d2,IM_loop2
  2567.         bra.s    IM_exit
  2568. IM_clrhlddec    move.w    #3*63-1,d0    ;no InstrExt => clear holdvals/decays
  2569. IM_loop3    clr.w    (a2)+        ;..and finetunes/flags/ext_psets
  2570.         dbf    d0,IM_loop3
  2571.         movea.l    (sp),a0
  2572. ; -------- For (very old) MMDs, with no InstrExt, set flags/SSFLG_LOOP,
  2573. ; -------- also copy inst_midipreset to ext_midipsets.
  2574.         movea.l    mmd_songinfo(a0),a3
  2575.         lea    flags,a2
  2576.     IFNE    MIDI
  2577.         lea    ext_midipsets,a1
  2578.     ENDC
  2579.         moveq    #62,d0
  2580. IM_loop4    cmp.w    #1,inst_replen(a3)
  2581.         bls.s    IM_noreptflg
  2582.         bset    #0,(a2)
  2583. IM_noreptflg    addq.l    #1,a2
  2584.     IFNE    MIDI
  2585.         move.b    inst_midipreset(a3),d1
  2586.         ext.w    d1
  2587.         move.w    d1,(a1)+
  2588.     ENDC
  2589.         addq.l    #8,a3        ;next inst
  2590.         dbf    d0,IM_loop4
  2591. IM_exit        addq.l    #4,sp
  2592.         movem.l    (sp)+,a2-a3/d2
  2593.         rts
  2594. ; *************************************************************************
  2595. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  2596. ; *************************************************************************
  2597. _InitPlayer:
  2598.     IFNE    MIDI
  2599.         bsr.w    _GetSerial
  2600.         tst.l    d0
  2601.         bne.s    IP_error
  2602.     ENDC
  2603.         bsr.w    _AudioInit
  2604.         tst.l    d0
  2605.         bne.s    IP_error
  2606.         rts
  2607. IP_error    bsr.s    _RemPlayer
  2608.         moveq    #-1,d0
  2609.         rts
  2610. ; *************************************************************************
  2611. ; RemPlayer() -- free interrupt, audio, serial port etc..
  2612. ; *************************************************************************
  2613. _RemPlayer:    move.b    _timeropen,d0
  2614.         beq.s    RP_notimer    ;timer is not ours
  2615.         bsr.s    _StopPlayer
  2616. RP_notimer:    bsr.w    _AudioRem
  2617.     IFNE    MIDI
  2618.         bra.w    _FreeSerial
  2619.     ELSEIF
  2620.         rts
  2621.     ENDC
  2622. ; *************************************************************************
  2623. ; StopPlayer() -- stop the music
  2624. ; *************************************************************************
  2625. _StopPlayer:    lea    DB,a1
  2626.         move.b    _timeropen-DB(a1),d0
  2627.         beq.s    SP_end        ;res. alloc fail.
  2628.     IFNE    CIAB
  2629.         movea.l    craddr-DB(a1),a0
  2630.         bclr    #0,(a0)        ;stop timer
  2631.     ENDC
  2632.     IFNE    AURA
  2633.         jsr    _RemAura(pc)
  2634.     ENDC
  2635.         move.l    _module-DB(a1),d0
  2636.         beq.s    SP_nomod
  2637.         move.l    d0,a0
  2638.         clr.w    mmd_pstate(a0)
  2639.         clr.l    _module-DB(a1)
  2640. SP_nomod
  2641.     IFNE    MIDI
  2642.         clr.b    lastcmdbyte-DB(a1)
  2643.     ENDC
  2644.         bra.w    SoundOff
  2645. SP_end        rts
  2646.  
  2647.  
  2648. _ContModule    tst.b    _timeropen
  2649.         beq.s    SP_end
  2650.         movea.l    craddr,a1
  2651.         bclr    #0,(a1)
  2652.         move.l    a0,-(sp)
  2653.         bsr.w    SoundOff
  2654.         move.l    (sp)+,a0
  2655.         moveq    #0,d0
  2656.         bra.s    contpoint
  2657. ; *************************************************************************
  2658. ; PlayModule(a0 = module)  -- initialize & play it!
  2659. ; *************************************************************************
  2660. _PlayModule:    st    d0
  2661. contpoint    movem.l    a0/d0,-(sp)
  2662.         bsr    _InitModule
  2663.         movem.l    (sp)+,a0/d0
  2664.         move.l    a6,-(sp)
  2665.         lea    DB,a6
  2666.         tst.b    _timeropen-DB(a6)
  2667.         beq    PM_end        ;resource allocation failure
  2668.         move.l    a0,d1
  2669.         beq    PM_end        ;module failure
  2670.     IFNE    CIAB
  2671.         movea.l    craddr-DB(a6),a1
  2672.         bclr    #0,(a1)        ;stop timer...
  2673.     ENDC
  2674.         clr.l    _module-DB(a6)
  2675.     IFNE    MIDI
  2676.         clr.b    lastcmdbyte-DB(a6)
  2677.     ENDC
  2678.         move.w    _modnum,d1
  2679.         beq.s    PM_modfound
  2680. PM_nextmod    tst.l    mmd_expdata(a0)
  2681.         beq.s    PM_modfound
  2682.         move.l    mmd_expdata(a0),a1
  2683.         tst.l    (a1)
  2684.         beq.s    PM_modfound        ;no more modules here!
  2685.         move.l    (a1),a0
  2686.         subq.w    #1,d1
  2687.         bgt.s    PM_nextmod
  2688. PM_modfound    cmp.b    #'T',3(a0)
  2689.         bne.s    PM_nomodT
  2690.         move.b    #'0',3(a0)    ;change MCNT to MCN0
  2691. PM_nomodT    movea.l    mmd_songinfo(a0),a1        ;song
  2692.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  2693.         btst    #0,msng_flags(a1)
  2694.         bne.s    PM_filon
  2695.         bset    #1,$bfe001
  2696.         bra.s    PM_filset
  2697. PM_filon    bclr    #1,$bfe001
  2698. PM_filset    tst.b    d0
  2699.         beq.s    PM_noclr
  2700.         clr.l    mmd_pline(a0)
  2701.         clr.l    rptline-DB(a6)
  2702.         clr.w    blkdelay-DB(a6)
  2703. ; ---------- Set 'pblock' and 'pseq' to correct values...
  2704. PM_noclr    cmp.b    #'2',3(a0)
  2705.         bne.s    PM_oldpbset
  2706.         move.w    mmd_psecnum(a0),d1
  2707.         move.l    a2,-(sp)        ;need extra register
  2708.         movea.l    msng_sections(a1),a2
  2709.         add.w    d1,d1
  2710.         move.w    0(a2,d1.w),d1        ;get sequence number
  2711.         add.w    d1,d1
  2712.         add.w    d1,d1
  2713.         move.w    d1,mmd_pseq(a0)
  2714.         movea.l    msng_pseqs(a1),a2
  2715.         movea.l    0(a2,d1.w),a2        ;PlaySeq...
  2716.         move.w    mmd_pseqnum(a0),d1
  2717.         add.w    d1,d1
  2718.         move.w    42(a2,d1.w),d1        ;and the correct block..
  2719.         move.l    (sp)+,a2
  2720.         bra.s    PM_setblk
  2721. PM_oldpbset    move.w    mmd_pseqnum(a0),d1
  2722.         add.w    #msng_playseq,d1
  2723.         move.b    0(a1,d1.w),d1        ;get first playseq entry
  2724.         ext.w    d1
  2725. PM_setblk    move.w    d1,mmd_pblock(a0)
  2726.         move.w    #-1,mmd_pstate(a0)
  2727.         move.l    a0,_module-DB(a6)
  2728.         btst    #5,msng_flags2(a1)    ;BPM?
  2729.         seq    bpmcounter-DB(a6)
  2730.     IFNE    CIAB
  2731.         move.w    msng_deftempo(a1),d0    ;get default tempo
  2732.         movea.l    craddr-DB(a6),a1
  2733.         bsr.w    _SetTempo    ;set default tempo
  2734.         bset    #0,(a1)        ;start timer => PLAY!!
  2735.     ENDC
  2736. PM_end        move.l    (sp)+,a6
  2737.         rts
  2738. ; *************************************************************************
  2739.  
  2740. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  2741.         lea    DB,a4
  2742.         moveq    #0,d2
  2743.         movea.l    4.w,a6
  2744. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  2745.     IFNE    AUDDEV
  2746.         moveq    #1,d2
  2747.         moveq    #-1,d0
  2748.         jsr    -$14a(a6)    ;AllocSignal()
  2749.         tst.b    d0
  2750.         bmi.w    initerr
  2751.         move.b    d0,sigbitnum-DB(a4)
  2752. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  2753.         lea    allocport-DB(a4),a1
  2754.         move.b    d0,15(a1)    ;set mp_SigBit
  2755.         move.l    a1,-(sp)
  2756.         suba.l    a1,a1
  2757.         jsr    -$126(a6)    ;FindTask(0)
  2758.         move.l    (sp)+,a1
  2759.         move.l    d0,16(a1)    ;set mp_SigTask
  2760.         lea    reqlist-DB(a4),a0
  2761.         move.l    a0,(a0)        ;NEWLIST begins...
  2762.         addq.l    #4,(a0)
  2763.         clr.l    4(a0)
  2764.         move.l    a0,8(a0)    ;NEWLIST ends...
  2765. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  2766.         moveq    #2,d2
  2767.         lea    allocreq-DB(a4),a1
  2768.         lea    audiodevname-DB(a4),a0
  2769.         moveq    #0,d0
  2770.         moveq    #0,d1
  2771.         movea.l    4.w,a6
  2772.         jsr    -$1bc(a6)    ;OpenDevice()
  2773.         tst.b    d0
  2774.         bne.w    initerr
  2775.         st    audiodevopen-DB(a4)
  2776. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open cia resource
  2777.         moveq    #3,d2
  2778.     ENDC
  2779.     IFNE    CIAB
  2780.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  2781.         beq.s    init_pal
  2782.         move.l    #474326,timerdiv-DB(a4) ;Assume that CIA freq is 715 909 Hz
  2783.         move.l    #3579545/2,bpmdiv-DB(a4)
  2784. init_pal    moveq    #0,d3
  2785.         lea    cianame-DB(a4),a1
  2786.         move.b    #'a',3(a1)
  2787. open_ciares    moveq    #0,d0
  2788.         movea.l    4.w,a6
  2789.         jsr    -$1f2(a6)    ;OpenResource()
  2790.         move.l    d0,_ciaresource
  2791.         beq.s    try_CIAB
  2792.         moveq    #4,d2
  2793.         move.l    d0,a6
  2794.         lea    timerinterrupt-DB(a4),a1
  2795.         moveq    #0,d0        ;Timer A
  2796.         jsr    -$6(a6)        ;AddICRVector()
  2797.         tst.l    d0
  2798.         beq.s    got_timer
  2799.         addq.l    #4,d3        ;add base addr index
  2800.         lea    timerinterrupt-DB(a4),a1
  2801.         moveq    #1,d0        ;Timer B
  2802.         jsr    -$6(a6)        ;AddICRVector()
  2803.         tst.l    d0
  2804.         beq.s    got_timer
  2805. try_CIAB    lea    cianame-DB(a4),a1
  2806.         cmp.b    #'a',3(a1)
  2807.         bne.s    initerr
  2808.         addq.b    #1,3(a1)
  2809.         moveq    #8,d3        ;CIAB base addr index = 8
  2810.         bra.w    open_ciares
  2811. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  2812. got_timer    lea    craddr+8-DB(a4),a6
  2813.         move.l    cia_addr(pc,d3.w),d0
  2814.         move.l    d0,(a6)
  2815.         sub.w    #$100,d0
  2816.         move.l    d0,-(a6)
  2817.         moveq    #2,d3        ;assume timer B
  2818.         btst    #9,d0        ;timer A or B ?
  2819.         bne.s    got_timerB
  2820.         subq.b    #1,d3        ;not timer B -> subtract 1
  2821.         add.w    #$100,d0    ;calc offset to timer control reg
  2822. got_timerB    add.w    #$900,d0
  2823.         move.l    d0,-(a6)
  2824.         move.l    d0,a0            ;get Control Register
  2825.         and.b    #%10000000,(a0)        ;clear CtrlReg bits 0 - 6
  2826.         move.b    d3,_timeropen-DB(a4)    ;d3: 1 = TimerA 2 = TimerB
  2827.     ENDC
  2828.     IFNE    VBLANK
  2829.         moveq    #5,d0        ;INTB_VERTB
  2830.         lea    timerinterrupt-DB(a4),a1
  2831.         jsr    -$a8(a6)    ;AddIntServer
  2832.         st    _timeropen-DB(a4)
  2833.     ENDC
  2834.         moveq    #0,d0
  2835. initret:    movem.l    (sp)+,a4/a6/d2-d3
  2836.         rts
  2837. initerr:    move.l    d2,d0
  2838.         bra.s    initret
  2839.  
  2840. cia_addr:    dc.l    $BFE501,$BFE701,$BFD500,$BFD700
  2841.  
  2842. _AudioRem:    movem.l    a5-a6,-(sp)
  2843.         lea    DB,a5
  2844.         moveq    #0,d0
  2845.         move.b    _timeropen,d0
  2846.         beq.s    rem1
  2847. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  2848.         clr.b    _timeropen
  2849.     IFNE    CIAB
  2850.         move.l    _ciaresource,a6
  2851.         lea    timerinterrupt-DB(a5),a1
  2852.         subq.b    #1,d0
  2853.         jsr    -$c(a6)        ;RemICRVector
  2854.     ENDC
  2855.     IFNE    VBLANK
  2856.         movea.l    4.w,a6
  2857.         lea    timerinterrupt(pc),a1
  2858.         moveq    #5,d0
  2859.         jsr    -$ae(a6)    ;RemIntServer
  2860.     ENDC
  2861. rem1:
  2862.     IFNE    AUDDEV
  2863.         movea.l    4.w,a6
  2864.         tst.b    audiodevopen-DB(a5)
  2865.         beq.s    rem2
  2866.         move.w    #$000f,$dff096    ;stop audio DMA
  2867. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  2868.         lea    allocreq-DB(a5),a1
  2869.         jsr    -$1c2(a6)    ;CloseDevice()
  2870.         clr.b    audiodevopen-DB(a5)
  2871. rem2:        moveq    #0,d0
  2872.         move.b    sigbitnum-DB(a5),d0
  2873.         bmi.s    rem3
  2874. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  2875.         jsr    -$150(a6)    ;FreeSignal()
  2876.         st    sigbitnum-DB(a5)
  2877. rem3:
  2878.     ENDC
  2879.         movem.l    (sp)+,a5-a6
  2880.         rts
  2881.  
  2882.     IFNE    MIDI
  2883. _GetSerial:    movem.l    a5-a6,-(sp)    ;Get serial port for MIDI
  2884.         lea    DB,a5
  2885.         bsr.s    GetSer2
  2886.         tst.l    d0        ;got the port??
  2887.         beq.s    rgser        ;yes
  2888.         movea.l    4.w,a6        ;no..try to flush serial.device:
  2889.         jsr    -$84(a6)        ;Forbid
  2890.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  2891.         lea    serdev-DB(a5),a1    ;"serial.device"
  2892.         jsr    -$114(a6)        ;FindName
  2893.         tst.l    d0
  2894.         beq.s    serdnotf        ;no serial.device!!
  2895.         move.l    d0,a1
  2896.         jsr    -$1b6(a6)        ;RemDevice
  2897. serdnotf:    jsr    -$8a(a6)        ;and Permit
  2898.         bsr.s    GetSer2        ;now try it again...
  2899. rgser:        movem.l    (sp)+,a5-a6
  2900.         rts
  2901.  
  2902. GetSer2:    movea.l    4.w,a6
  2903.         moveq    #0,d0
  2904.         lea    miscresname-DB(a5),a1
  2905.         jsr    -$1f2(a6)    ;OpenResource()
  2906.         move.l    d0,miscresbase-DB(a5)
  2907.         tst.l    d0
  2908.         beq.s    gserror
  2909.         move.l    d0,a6
  2910.         lea    medname-DB(a5),a1
  2911.         moveq    #0,d0        ;serial port
  2912.         jsr    -$6(a6)        ;AllocMiscResource()
  2913.         tst.l    d0
  2914.         bne.s    gserror
  2915.         lea    medname-DB(a5),a1
  2916.         moveq    #1,d0        ;serial bits
  2917.         jsr    -$6(a6)
  2918.         tst.l    d0
  2919.         beq.s    gs2_allocok
  2920.         moveq    #0,d0
  2921.         jsr    -$c(a6)        ;bits failed -> Free serial port
  2922.         bra.s    gserror
  2923. gs2_allocok    move.w    $dff01c,d0
  2924.         btst    #0,d0
  2925.         sne    intrson-DB(a5)
  2926.         moveq    #0,d0        ;TBE
  2927.         lea    serinterrupt-DB(a5),a1
  2928.         move.l    4.w,a6
  2929.         jsr    -$a2(a6)    ;SetIntVector()
  2930.         move.l    d0,prevtbe-DB(a5)
  2931.         move.w    #$8001,$dff09a    ;TBE on
  2932.         move.w    #114,$dff032    ;set baud rate (SERPER)
  2933.         st    serportalloc-DB(a5)
  2934.         moveq    #0,d0
  2935.         rts
  2936. gserror:    moveq    #-1,d0
  2937.         rts
  2938.  
  2939. _FreeSerial:    movem.l    a5-a6,-(sp)
  2940.         lea    DB,a5
  2941.         tst.l    miscresbase-DB(a5)
  2942.         beq.s    retfs
  2943.         tst.b    serportalloc-DB(a5)
  2944.         beq.s    retfs
  2945. wmb_loop    move.w    $dff018,d0    ;WAIT until all data sent
  2946.         btst    #12,d0        ;test TSRE bit of SERDAT
  2947.         beq.s    wmb_loop
  2948.         move.w    #$0001,$dff09a    ;disable TBE
  2949.         movea.l    4.w,a6
  2950.         move.l    prevtbe-DB(a5),a1
  2951.         moveq    #0,d0
  2952.         jsr    -$a2(a6)    ;SetIntVector()
  2953. fs_noptbe    movea.l    miscresbase-DB(a5),a6
  2954.         moveq    #0,d0        ;serial port
  2955.         jsr    -$c(a6)        ;FreeMiscResource()
  2956.         moveq    #1,d0        ;serial bits
  2957.         jsr    -$c(a6)
  2958.         clr.b    serportalloc-DB(a5)
  2959.         clr.b    lastcmdbyte-DB(a5)
  2960. retfs:        movem.l    (sp)+,a5-a6
  2961.         rts
  2962.  
  2963. ; Message number in d0.
  2964. _InitMIDIDump:    tst.b    serportalloc
  2965.         beq.s    idd_rts
  2966.         movem.l    a1/a5/a6,-(sp)    ;a1 = data pointer, d1 = length
  2967.         lea    DB,a5
  2968.         movea.l    4.w,a6            ;ExecBase
  2969.         jsr    -$78(a6)        ;Disable()
  2970.         cmp.w    #16,dqentries-DB(a5)    ;dump queue full?
  2971.         bge.s    idd_exit        ;exit without doing anything
  2972.         lea    dqwriteptr-DB(a5),a1
  2973.         movea.l    (a1),a0
  2974.         move.w    d0,(a0)+        ;store message number
  2975.         cmpa.l    a1,a0            ;queue end?
  2976.         bne.s    idd_noresetbuff
  2977.         lea    dumpqueue-DB(a5),a0    ;reset write pointer
  2978. idd_noresetbuff    move.l    a0,(a1)            ;and write it back.
  2979.         addq.w    #1,dqentries-DB(a5)
  2980.         tst.b    sysx-DB(a5)        ;already sending data?
  2981.         bne.s    idd_exit        ;yes. Don't initiate new send.
  2982.         clr.b    lastcmdbyte-DB(a5)
  2983.         bsr    StartNewDump
  2984.         move.w    $dff018,d0        ;SERDATR
  2985.         btst    #13,d0
  2986.         beq.s    idd_exit
  2987.         move.w    #$8001,$dff09c        ;request TBE
  2988. idd_exit    jsr    -$7e(a6)        ;Enable()
  2989.         movem.l    (sp)+,a1/a5/a6
  2990. idd_rts        rts
  2991.  
  2992. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable..(Interrupts are enabled anyway)
  2993.         move.w    #1,$9c(a0)            ;clear intreq bit
  2994.         tst.b    sysx-buffptr(a1)        ;sysx??
  2995.         bne.s    sih_sysx
  2996.         move.w    bytesinbuff-buffptr(a1),d0    ;bytesinbuff
  2997.         beq.s    exsih                ;buffer empty
  2998.         movea.l    readbuffptr-buffptr(a1),a5    ;get buffer read pointer
  2999.         move.w    #$100,d1            ;Stop bit
  3000.         move.b    (a5)+,d1            ;get byte
  3001.         move.w    d1,$30(a0)            ;and push it to SERDAT
  3002.         cmpa.l    a1,a5                ;shall we reset ptr?
  3003.         bne.s    norrbuffptr            ;not yet..
  3004.         lea    -256(a1),a5
  3005. norrbuffptr    subq.w    #1,d0                ;one less bytes in buffer
  3006.         move.w    d0,bytesinbuff-buffptr(a1)    ;remember it
  3007.         move.l    a5,readbuffptr-buffptr(a1)    ;push new read ptr back
  3008. exsih        move.w    #$c000,$9a(a0)
  3009.         rts
  3010. sih_sysx    move.w    #$100,d1
  3011.         movea.l    sysxptr-buffptr(a1),a5    ;data pointer
  3012.         move.b    (a5)+,d1
  3013.         move.l    a5,sysxptr-buffptr(a1)
  3014.         move.w    d1,$30(a0)        ;-> SERDAT
  3015.         subq.l    #1,sysxleft-buffptr(a1)    ;sub data left length
  3016.         bne.s    exsih        ;not 0w
  3017.         lea    DB,a5
  3018.         clr.b    lastcmdbyte-DB(a5)
  3019.         bsr.s    StartNewDump
  3020.         bra.s    exsih
  3021.  
  3022. StartNewDump:    tst.w    dqentries-DB(a5)    ;queue empty?
  3023.         beq.s    snd_exit2
  3024.         movea.l    dqreadptr-DB(a5),a1    ;get read pointer
  3025.         move.w    (a1)+,d0        ;get message number (D0)
  3026.         cmpa.l    #dqwriteptr,a1        ;queue end?
  3027.         bne.s    snd_noresetbuff
  3028.         lea    dumpqueue-DB(a5),a1    ;reset write pointer
  3029. snd_noresetbuff    move.l    a1,dqreadptr-DB(a5)    ;and write it back.
  3030.         subq.w    #1,dqentries-DB(a5)
  3031. ; then attempt to search the given message (# in D0)
  3032.         move.l    _module-DB(a5),d1
  3033.         beq.s    StartNewDump
  3034.         move.l    d1,a1
  3035.         move.l    mmd_expdata(a1),d1
  3036.         beq.s    StartNewDump
  3037.         move.l    d1,a1
  3038.         move.l    52(a1),d1        ;exp_dump
  3039.         beq.s    StartNewDump
  3040.         move.l    d1,a1
  3041.         cmp.w    (a1),d0
  3042.         bge.s    StartNewDump
  3043.         addq.l    #8,a1            ;points to MMDDump ptr table
  3044.         add.w    d0,d0
  3045.         add.w    d0,d0            ;number *= 4
  3046.         adda.w    d0,a1
  3047.         movea.l    (a1),a1
  3048. ; initialize send variables (msg addr. in A0)
  3049. snd_found    move.l    (a1)+,sysxleft-DB(a5)    ;length
  3050.         move.l    (a1),sysxptr-DB(a5)    ;data pointer
  3051.         st    sysx-DB(a5)
  3052.         rts
  3053. snd_exit2    clr.b    sysx-DB(a5)        ;finish dump
  3054.         rts
  3055.  
  3056. _AddMIDIData    move.l    a6,-(sp)
  3057.         lea    DB,a6
  3058.         bsr.s    _AddMIDId
  3059.         move.l    (sp)+,a6
  3060.         rts
  3061.  
  3062. _AddMIDId    movem.l    a1-a3/a5,-(sp)
  3063.         tst.b    serportalloc-DB(a6)
  3064.         beq.s    retamd1
  3065.         movea.l    4.w,a5
  3066.         lea    $dff09a,a3
  3067.         move.w    #$4000,(a3)    ;Disable interrupts
  3068.         addq.b    #1,$126(a5)    ;ExecBase->IDNestCnt
  3069.         lea    buffptr-DB(a6),a2    ;end of buffer (ptr)
  3070.         move.w    -130(a3),d1    ;-130(a3) = $dff018 (SERDATR)
  3071.         btst    #13,d1
  3072.         beq.s    noTBEreq
  3073.         move.w    #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  3074. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  3075.         subq.w    #1,d0        ;-1 for DBF
  3076. adddataloop    move.b    (a0)+,d1    ;get byte
  3077.         bpl.s    norscheck    ;this isn't a status byte
  3078.         cmp.b    #$ef,d1        ;ignore system messages
  3079.         bhi.s    norscheck
  3080.         cmp.b    lastcmdbyte-DB(a6),d1    ;same as previous status byte?
  3081.         beq.s    samesb            ;yes, skip
  3082.         move.b    d1,lastcmdbyte-DB(a6)    ;no, don't skip but store.
  3083. norscheck    move.b    d1,(a1)+        ;push to midi send buffer
  3084.         addq.w    #1,8(a2)
  3085. samesb        cmpa.l    a2,a1            ;end of buffer??
  3086.         bne.s    noresbuffptr        ;no.
  3087.         lea    sendbuffer-DB(a6),a1    ;reset
  3088. noresbuffptr    dbf    d0,adddataloop
  3089.         move.l    a1,(a2)            ;push back new buffer ptr
  3090.         subq.b    #1,$126(a5)
  3091.         bge.s    retamd1
  3092.         move.w    #$c000,(a3)    ;enable interrupts again
  3093. retamd1        movem.l    (sp)+,a1-a3/a5
  3094.         rts
  3095.     ENDC
  3096.  
  3097.         DATA
  3098. DB:        ;Data base pointer
  3099.     IFNE    MIDI
  3100. sendbuffer    ds.b    256
  3101. buffptr        dc.l    sendbuffer
  3102. readbuffptr    dc.l    sendbuffer
  3103. bytesinbuff    dc.w    0
  3104. sysx        dc.b    0
  3105. lastcmdbyte    dc.b    0
  3106. sysxptr        dc.l    0
  3107. sysxleft    dc.l    0
  3108. dumpqueue    ds.w    16
  3109. dqwriteptr    dc.l    dumpqueue
  3110. dqreadptr    dc.l    dumpqueue
  3111. dqentries    dc.w    0
  3112.     ENDC
  3113. miscresbase    dc.l    0
  3114. timerdiv    dc.l    470000
  3115.     IFNE    AUDDEV
  3116. audiodevopen    dc.b    0
  3117. sigbitnum    dc.b    -1
  3118.     ENDC
  3119.     IFNE    MIDI
  3120. serportalloc    dc.b    0
  3121.     ENDC
  3122.         even
  3123.     IFNE    MIDI
  3124. preschgdata    dc.l    0
  3125. noteondata    dc.l    0
  3126.     ENDC
  3127. _module        dc.l    0
  3128. dmaonmsk    dc.w    0 ;\_May not be
  3129.     IFNE    MIDI
  3130. bytesinnotebuff    dc.w    0 ;/ separated!
  3131. noteonbuff    ds.b    (MAX_NUMTRACKS+2)*3
  3132.         even
  3133. intrson        dc.b    0,0
  3134. prevtbe        dc.l    0
  3135.     ENDC
  3136.     IFNE    CIAB
  3137. _ciaresource    dc.l    0
  3138. craddr        dc.l    0
  3139.         dc.l    0    ;tloaddr
  3140.         dc.l    0    ;thiaddr
  3141.     ENDC
  3142. timerinterrupt    dc.w    0,0,0,0,0
  3143.         dc.l    timerintname,DB
  3144.         dc.l    _IntHandler
  3145.     IFNE    MIDI
  3146. serinterrupt    dc.w    0,0,0,0,0
  3147.         dc.l    serintname,buffptr,SerIntHandler
  3148.     ENDC
  3149.     IFNE    AUDDEV
  3150. allocport    dc.l    0,0    ;succ, pred
  3151.         dc.b    4,0    ;NT_MSGPORT
  3152.         dc.l    0    ;name
  3153.         dc.b    0,0    ;flags = PA_SIGNAL
  3154.         dc.l    0    ;task
  3155. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  3156.         dc.b    5,0
  3157. allocreq    dc.l    0,0
  3158.         dc.b    0,127    ;NT_UNKNOWN, use maximum priority (127)
  3159.         dc.l    0,allocport    ;name, replyport
  3160.         dc.w    68        ;length
  3161.         dc.l    0    ;io_Device
  3162.         dc.l    0    ;io_Unit
  3163.         dc.w    0    ;io_Command
  3164.         dc.b    0,0    ;io_Flags, io_Error
  3165.         dc.w    0    ;ioa_AllocKey
  3166.         dc.l    sttempo    ;ioa_Data
  3167.         dc.l    1    ;ioa_Length
  3168.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  3169.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  3170. audiodevname    dc.b    'audio.device',0
  3171.     ENDC
  3172.     IFNE    CIAB
  3173. cianame        dc.b    'ciax.resource',0
  3174. _timeropen    dc.b    0
  3175.     ENDC
  3176. timerintname    dc.b    'OMEDTimerInterrupt',0
  3177.     IFNE    MIDI
  3178. serintname    dc.b    'OMEDSerialInterrupt',0
  3179. miscresname    dc.b    'misc.resource',0
  3180. serdev        dc.b    'serial.device',0
  3181. medname        dc.b    'OctaMED Pro modplayer',0
  3182.     ENDC
  3183.         even
  3184.     IFNE    MIDI
  3185. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  3186.  
  3187. midicontrnum    ds.b    16
  3188.  
  3189. prevmidicpres    dc.l    0,0,0,0,0,0,0,0 ; 16 * 2 bytes
  3190.  
  3191. prevmidipbend    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3192.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  3193.     ENDC
  3194. ; TRACK-data structures (see definitions at the end of this file)
  3195. t03d        ds.b    TAAOFFS
  3196.         dc.l    $dff0a0
  3197.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3198.         dc.b    $ff
  3199. t03de        ds.b    T03SZ-(t03de-t03d)
  3200.         ds.b    TAAOFFS
  3201.         dc.l    $dff0b0
  3202.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3203.         dc.b    $ff
  3204.         ds.b    T03SZ-(t03de-t03d)
  3205.         ds.b    TAAOFFS
  3206.         dc.l    $dff0c0
  3207.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3208.         dc.b    $ff
  3209.         ds.b    T03SZ-(t03de-t03d)
  3210.         ds.b    TAAOFFS
  3211.         dc.l    $dff0d0
  3212.         ds.b    TTMPVOLOFFS-(TAAOFFS+4)
  3213.         dc.b    $ff
  3214.         ds.b    T03SZ-(t03de-t03d)
  3215. t463d        ds.b    (MAX_NUMTRACKS-4)*T415SZ
  3216. trackdataptrs    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  3217. ; Build pointer table. This works on Devpac assembler, other assemblers
  3218. ; may need modifications.
  3219. TRKCOUNT    SET    0
  3220.         REPT    (MAX_NUMTRACKS-4)
  3221.         dc.l    t463d+TRKCOUNT
  3222. TRKCOUNT    SET    TRKCOUNT+T415SZ
  3223.         ENDR
  3224.  
  3225. nextblock    dc.b    0 ;\ DON'T SEPARATE
  3226. nxtnoclrln    dc.b    0 :/
  3227. numtracks    dc.w    0 ;\ DON'T SEPARATE
  3228. numlines    dc.w    0 ;/
  3229. numpages    dc.w    0
  3230. nextblockline    dc.w    0
  3231. rptline        dc.w    0 ;\ DON'T SEPARATE
  3232. rptcounter    dc.w    0 ;/
  3233. blkdelay    dc.w    0    ;block delay (PT PatternDelay)
  3234. bpmcounter    dc.w    0
  3235. bpmdiv        dc.l    3546895/2
  3236. fxplineblk    dc.l    0    ;for reading effects
  3237.  
  3238. ; Fields in struct InstrExt (easier to access this way rather than
  3239. ; searching through the module).
  3240. holdvals    ds.b 63
  3241. decays        ds.b 63
  3242. finetunes    ds.b 63
  3243. flags        ds.b 63
  3244. ext_midipsets    ds.w 63
  3245. outputdevs    ds.b 63
  3246. playing_aura    ds.b 1
  3247.         EVEN
  3248.  
  3249. ; Below are the period tables. There's one table for each finetune position.
  3250.     IFNE    SYNTH|IFFMOCT
  3251.     dc.w    3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812
  3252.     dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
  3253.     ENDC
  3254. per0    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  3255.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  3256.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3257.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3258.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3259.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  3260.     IFNE    SYNTH|IFFMOCT
  3261.     dc.w    3400,3209,3029,2859,2699,2547,2404,2269,2142,2022,1908,1801
  3262.     dc.w    1700,1605,1515,1430,1349,1274,1202,1135,1071,1011,954,901
  3263.     ENDC
  3264. per1    dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  3265.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  3266.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3267.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3268.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3269.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  3270.     IFNE    SYNTH|IFFMOCT
  3271.     dc.w    3376,3187,3008,2839,2680,2529,2387,2253,2127,2007,1895,1788
  3272.     dc.w    1688,1593,1504,1419,1340,1265,1194,1127,1063,1004,947,894
  3273.     ENDC
  3274. per2    dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  3275.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  3276.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3277.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3278.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3279.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  3280.     IFNE    SYNTH|IFFMOCT
  3281.     dc.w    3352,3164,2986,2819,2660,2511,2370,2237,2112,1993,1881,1776
  3282.     dc.w    1676,1582,1493,1409,1330,1256,1185,1119,1056,997,941,888
  3283.     ENDC
  3284. per3    dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  3285.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  3286.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3287.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3288.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3289.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  3290.     IFNE    SYNTH|IFFMOCT
  3291.     dc.w    3328,3141,2965,2799,2641,2493,2353,2221,2097,1979,1868,1763
  3292.     dc.w    1664,1571,1482,1399,1321,1247,1177,1111,1048,989,934,881
  3293.     ENDC
  3294. per4    dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  3295.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  3296.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3297.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3298.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3299.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  3300.     IFNE    SYNTH|IFFMOCT
  3301.     dc.w    3304,3119,2944,2778,2622,2475,2336,2205,2081,1965,1854,1750
  3302.     dc.w    1652,1559,1472,1389,1311,1238,1168,1103,1041,982,927,875
  3303.     ENDC
  3304. per5    dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  3305.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  3306.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3307.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3308.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3309.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  3310.     IFNE    SYNTH|IFFMOCT
  3311.     dc.w    3280,3096,2922,2758,2603,2457,2319,2189,2066,1950,1841,1738
  3312.     dc.w    1640,1548,1461,1379,1302,1229,1160,1095,1033,975,920,869
  3313.     ENDC
  3314. per6    dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  3315.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  3316.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3317.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3318.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3319.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  3320.     IFNE    SYNTH|IFFMOCT
  3321.     dc.w    3256,3073,2901,2738,2584,2439,2302,2173,2051,1936,1827,1725
  3322.     dc.w    1628,1537,1450,1369,1292,1220,1151,1087,1026,968,914,862
  3323.     ENDC
  3324. per7    dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  3325.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  3326.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3327.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3328.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3329.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  3330.     IFNE    SYNTH|IFFMOCT
  3331.     dc.w    3628,3424,3232,3051,2880,2718,2565,2421,2285,2157,2036,1922
  3332.     dc.w    1814,1712,1616,1525,1440,1359,1283,1211,1143,1079,1018,961
  3333.     ENDC
  3334. per_8    dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  3335.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  3336.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3337.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3338.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3339.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  3340.     IFNE    SYNTH|IFFMOCT
  3341.     dc.w    3588,3387,3197,3017,2848,2688,2537,2395,2260,2133,2014,1901
  3342.     dc.w    1794,1693,1598,1509,1424,1344,1269,1197,1130,1067,1007,950
  3343.     ENDC
  3344. per_7    dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  3345.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  3346.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3347.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3348.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3349.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  3350.     IFNE    SYNTH|IFFMOCT
  3351.     dc.w    3576,3375,3186,3007,2838,2679,2529,2387,2253,2126,2007,1894
  3352.     dc.w    1788,1688,1593,1504,1419,1339,1264,1193,1126,1063,1003,947
  3353.     ENDC
  3354. per_6    dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  3355.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  3356.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3357.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3358.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3359.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  3360.     IFNE    SYNTH|IFFMOCT
  3361.     dc.w    3548,3349,3161,2984,2816,2658,2509,2368,2235,2110,1991,1879
  3362.     dc.w    1774,1674,1580,1492,1408,1329,1254,1184,1118,1055,996,940
  3363.     ENDC
  3364. per_5    dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  3365.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  3366.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3367.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3368.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3369.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  3370.     IFNE    SYNTH|IFFMOCT
  3371.     dc.w    3524,3326,3140,2963,2797,2640,2492,2352,2220,2095,1978,1867
  3372.     dc.w    1762,1663,1570,1482,1399,1320,1246,1176,1110,1048,989,933
  3373.     ENDC
  3374. per_4    dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  3375.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  3376.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3377.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3378.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3379.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3380.     IFNE    SYNTH|IFFMOCT
  3381.     dc.w    3500,3304,3118,2943,2778,2622,2475,2336,2205,2081,1964,1854
  3382.     dc.w    1750,1652,1559,1472,1389,1311,1237,1168,1102,1041,982,927
  3383.     ENDC
  3384. per_3    dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  3385.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  3386.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3387.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3388.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3389.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3390.     IFNE    SYNTH|IFFMOCT
  3391.     dc.w    3472,3277,3093,2920,2756,2601,2455,2317,2187,2064,1949,1839
  3392.     dc.w    1736,1639,1547,1460,1378,1301,1228,1159,1094,1032,974,920
  3393.     ENDC
  3394. per_2    dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  3395.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  3396.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3397.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3398.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3399.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3400.     IFNE    SYNTH|IFFMOCT
  3401.     dc.w    3448,3254,3072,2899,2737,2583,2438,2301,2172,2050,1935,1827
  3402.     dc.w    1724,1627,1536,1450,1368,1292,1219,1151,1086,1025,968,913
  3403.     ENDC
  3404. per_1    dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  3405.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  3406.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3407.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3408.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3409.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3410.  
  3411. _periodtable
  3412.     dc.l    per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
  3413.     dc.l    per1,per2,per3,per4,per5,per6,per7
  3414.  
  3415.     IFND    __G2
  3416.         section "datachip",data,chip ;for A68k
  3417.     ENDC
  3418.     IFD    __G2
  3419.         section "datachip",data_c ;this is for Devpac 2
  3420.     ENDC
  3421.         XDEF    _modnum
  3422.     IFNE    EASY
  3423. easymod        INCBIN    "module"    ;<<<<< MODULE NAME HERE!
  3424.     ENDC
  3425. _chipzero    dc.l    0
  3426. _modnum        dc.w    0    ;number of module to play
  3427.  
  3428. ; macros for entering offsets
  3429. DEFWORD    MACRO
  3430. \1    EQU    OFFS
  3431. OFFS    SET    OFFS+2
  3432.     ENDM
  3433. DEFBYTE    MACRO
  3434. \1    EQU    OFFS
  3435. OFFS    SET    OFFS+1
  3436.     ENDM
  3437. DEFLONG    MACRO
  3438. \1    EQU    OFFS
  3439. OFFS    SET    OFFS+4
  3440.     ENDM
  3441.  
  3442. OFFS    SET    0
  3443. ; the track-data structure definition:
  3444.     DEFBYTE    trk_prevnote    ;previous note number (0 = none, 1 = C-1..)
  3445.     DEFBYTE    trk_previnstr    ;previous instrument number
  3446.     DEFBYTE    trk_prevvol    ;previous volume
  3447.     DEFBYTE    trk_prevmidich    ;previous MIDI channel
  3448.     DEFBYTE    trk_prevmidin    ;previous MIDI note
  3449.     DEFBYTE    trk_noteoffcnt    ;note-off counter (hold)
  3450.     DEFBYTE    trk_inithold    ;default hold for this instrument
  3451.     DEFBYTE    trk_initdecay    ;default decay for....
  3452.     DEFBYTE    trk_stransp    ;instrument transpose
  3453.     DEFBYTE    trk_finetune    ;finetune
  3454.     DEFWORD    trk_soffset    ;new sample offset | don't sep this and 2 below!
  3455.     DEFBYTE    trk_miscflags    ;bit: 7 = cmd 3 exists, 0 = cmd E exists
  3456.     DEFBYTE    trk_currnote    ;note on CURRENT line (0 = none, 1 = C-1...)
  3457.     DEFBYTE    trk_outputdev    ;output device
  3458.     DEFBYTE    trk_fxtype    ;fx type: 0 = norm, 1 = none, -1 = MIDI
  3459.     DEFLONG    trk_previnstra    ;address of the previous instrument data
  3460.     DEFWORD    trk_trackvol
  3461. ; the following data only on tracks 0 - 3
  3462.     DEFWORD    trk_prevper    ;previous period
  3463.     DEFLONG    trk_audioaddr    ;hardware audio channel base address
  3464.     DEFLONG    trk_sampleptr    ;pointer to sample
  3465.     DEFWORD    trk_samplelen    ;length (>> 1)
  3466.     DEFWORD    trk_porttrgper    ;portamento (cmd 3) target period
  3467.     DEFBYTE    trk_vibshift    ;vibrato shift for ASR instruction
  3468.     DEFBYTE    trk_vibrspd    ;vibrato speed/size (cmd 4 qualifier)
  3469.     DEFWORD    trk_vibrsz    ;vibrato size
  3470.     DEFLONG    trk_synthptr    ;pointer to synthetic/hybrid instrument
  3471.     DEFWORD    trk_arpgoffs    ;SYNTH: current arpeggio offset
  3472.     DEFWORD    trk_arpsoffs    ;SYNTH: arpeggio restart offset
  3473.     DEFBYTE    trk_volxcnt    ;SYNTH: volume execute counter
  3474.     DEFBYTE    trk_wfxcnt    ;SYNTH: waveform execute counter
  3475.     DEFWORD    trk_volcmd    ;SYNTH: volume command pointer
  3476.     DEFWORD    trk_wfcmd    ;SYNTH: waveform command pointer
  3477.     DEFBYTE    trk_volwait    ;SYNTH: counter for WAI (volume list)
  3478.     DEFBYTE    trk_wfwait    ;SYNTH: counter for WAI (waveform list)
  3479.     DEFWORD    trk_synthvibspd    ;SYNTH: vibrato speed
  3480.     DEFWORD    trk_wfchgspd    ;SYNTH: period change
  3481.     DEFWORD    trk_perchg    ;SYNTH: curr. period change from trk_prevper
  3482.     DEFLONG    trk_envptr    ;SYNTH: envelope waveform pointer
  3483.     DEFWORD    trk_synvibdep    ;SYNTH: vibrato depth
  3484.     DEFLONG    trk_synvibwf    ;SYNTH: vibrato waveform
  3485.     DEFWORD    trk_synviboffs    ;SYNTH: vibrato pointer
  3486.     DEFBYTE    trk_initvolxspd    ;SYNTH: volume execute speed
  3487.     DEFBYTE    trk_initwfxspd    ;SYNTH: waveform execute speed
  3488.     DEFBYTE    trk_volchgspd    ;SYNTH: volume change
  3489.     DEFBYTE    trk_prevnote2    ;SYNTH: previous note
  3490.     DEFBYTE    trk_synvol    ;SYNTH: current volume
  3491.     DEFBYTE    trk_synthtype    ;>0 = synth, -1 = hybrid, 0 = no synth
  3492.     DEFLONG    trk_periodtbl    ;pointer to period table
  3493.     DEFWORD    trk_prevportspd    ;portamento (cmd 3) speed
  3494.     DEFBYTE    trk_decay    ;decay
  3495.     DEFBYTE    trk_fadespd    ;decay speed
  3496.     DEFLONG    trk_envrestart    ;SYNTH: envelope waveform restart point
  3497.     DEFBYTE    trk_envcount    ;SYNTH: envelope counter
  3498.     DEFBYTE    trk_split    ;0 = this channel not splitted (OctaMED V2)
  3499.     DEFWORD    trk_newper    ;new period (for synth use)
  3500.     DEFBYTE    trk_vibroffs    ;vibrato table offset \ DON'T SEPARATE
  3501.     DEFBYTE    trk_tremoffs    ;tremolo table offset /
  3502.     DEFWORD    trk_tremsz    ;tremolo size
  3503.     DEFBYTE    trk_tremspd    ;tremolo speed
  3504.     DEFBYTE    trk_tempvol    ;temporary volume (for tremolo)
  3505.     DEFWORD    trk_vibradjust    ;vibrato +/- change from base period \ DON'T SEPARATE
  3506.     DEFWORD    trk_arpadjust    ;arpeggio +/- change from base period/
  3507.         END
  3508.