home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaMiscModsCD3.iso / _PROGRAMME / TRACKER / OctaMED.lzh / OctaMED / Programmers / MODPlayer / mod8player.a < prev    next >
Encoding:
Text File  |  1993-03-13  |  35.5 KB  |  1,303 lines

  1. ;    mod8player.a
  2. ;    ~~~~~~~~~~~~
  3. ;    The player routine for OctaMED V2.00 5 - 8 channel songs.
  4. ;    Written by Teijo Kinnunen in 1991.
  5.  
  6. ;============================================================================
  7.  
  8. ;the MMD0 structure offsets
  9. mmd_id        EQU    0
  10. mmd_modlen    EQU    4
  11. mmd_songinfo    EQU    8
  12. mmd_songlen    EQU    12    ;currently unused
  13. mmd_blockarr    EQU    16
  14. mmd_blockarrlen    EQU    20    ;unused
  15. mmd_smplarr    EQU    24
  16. mmd_smplarrlen    EQU    28    ;unused
  17. mmd_expdata    EQU    32
  18. mmd_expsize    EQU    36    ;unused
  19. mmd_pstate    EQU    40
  20. mmd_pblock    EQU    42
  21. mmd_pline    EQU    44
  22. mmd_pseqnum    EQU    46
  23. mmd_actplayline    EQU    48    ;obsolete
  24. mmd_counter    EQU    50
  25. mmd_songsleft    EQU    51
  26.  
  27. ;the MMD0song structure
  28. ;Instrument data here (504 bytes = 63 * 8)
  29. msng_numblocks    EQU    504
  30. msng_songlen    EQU    506
  31. msng_playseq    EQU    508
  32. msng_deftempo    EQU    764
  33. msng_playtransp    EQU    766
  34. msng_flags    EQU    767
  35. msng_reserved    EQU    768
  36. msng_tempo2    EQU    769
  37. msng_trkvol    EQU    770
  38. msng_mastervol    EQU    786
  39. msng_numsamples    EQU    787
  40.  
  41. ;Instrument data
  42. inst_repeat    EQU    0
  43. inst_replen    EQU    2
  44. inst_midich    EQU    4
  45. inst_midipreset    EQU    5
  46. inst_svol    EQU    6
  47. inst_strans    EQU    7
  48.  
  49. ;Audio hardware offsets
  50.  
  51. ac_ptr    EQU    $00
  52. ac_len    EQU    $04
  53. ac_per    EQU    $06
  54. ac_vol    EQU    $08
  55. ; These are not in real hardware, but the player "emulates" the real
  56. ; hardware. And there are some extra registers that we require.
  57. ac_end    EQU    $0C
  58. ac_rest    EQU    $10
  59. ac_mask    EQU    $14
  60. ac_rhw    EQU    $16
  61. T03SZ    EQU    88
  62.  
  63.         section    "text",code
  64.  
  65. sinetable:    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  66.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  67.         dc.b    -106,-90,-71,-49,-25,0
  68.  
  69. nextblock:    dc.w    0
  70. numtracks:    dc.w    0
  71. numlines:    dc.w    0
  72.  
  73. _Wait1line:    move.l    d0,-(sp)
  74.         moveq    #$79,d0
  75. wl0:        move.b    $dff007,d1
  76. wl1:        cmp.b    $dff007,d1
  77.         beq.s    wl1
  78.         dbf    d0,wl0
  79.         move.l    (sp)+,d0
  80.         rts
  81.  
  82. getinsdata:    moveq    #0,d2
  83.         move.w    4(a0),d0    ;Soitin-struct in a0
  84.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  85.         move.l    a0,d0
  86.         lea    _periods(pc),a0
  87.         move.l    a0,trk_periodtbl(a5)
  88.         add.b    d1,d1
  89.         move.w    0(a0,d1.w),d5 ;put period to d5
  90.         move.l    d0,a0
  91.         addq.l    #6,d0        ;Skip structure
  92.         move.l    (a0),d1        ;length
  93.         move.w    (a3),d2        ;inst_repeat (offs. 0)
  94.         move.w    inst_replen(a3),d3
  95.         rts
  96. iff5or3oct:    movem.l    d6-d7,-(sp)
  97.         moveq    #0,d7
  98.         move.w    d1,d7
  99.         divu    #12,d7    ;octave #
  100.         move.l    d7,d5
  101.         swap    d5    ;note number in this oct (0-11) is in d5
  102.         move.l    (a0),d1
  103.         cmp.b    #2,d0
  104.         bne.s    no3oct
  105.         addq.l    #6,d7
  106.         divu    #7,d1    ;get length of the 1st octave
  107.         bra.s    no5oct
  108. no3oct:        divu    #31,d1    ;get length of the 1st octave (5 octaves)
  109. no5oct:        move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  110.         move.w    (a3),d2        ;inst_repeat
  111.         move.w    inst_replen(a3),d3
  112.         moveq    #0,d6
  113.         move.b    shiftcnt(pc,d7.w),d6
  114.         lsl.w    d6,d2
  115.         lsl.w    d6,d3
  116.         lsl.w    d6,d1
  117.         move.b    mullencnt(pc,d7.w),d6
  118.         mulu    d6,d0        ;offset of this oct from 1st oct
  119.         add.l    a0,d0        ;add base address to offset
  120.         addq.l    #6,d0        ;skip structure
  121.         lea    _periods(pc),a1
  122.         add.b    octstart(pc,d7.w),d5
  123.         add.b    d5,d5
  124.         move.w    0(a1,d5.w),d5
  125.         movem.l    (sp)+,d6-d7
  126.         rts    ;returns period in d5
  127. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0
  128. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0
  129. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36
  130.  
  131. ;**************************************************************************
  132. ;*
  133. ;*        8 CHANNEL PLAY ROUTINE
  134. ;*
  135. ;**************************************************************************
  136. _ChannelO8:    cmp.b    #8,d0
  137.         bge.s    xco8
  138.         lea    trackdata8(pc),a1
  139.         lsl.b    #2,d0
  140.         adda.w    d0,a1
  141.         movea.l    (a1),a1
  142.         movea.l    trk_audioaddr(a1),a1
  143.         clr.w    ac_per(a1)
  144. xco8        rts
  145.  
  146. _PlayNote8:    ;d0(w) = trk #, d1 = note #, d2 = vol, d3(w) = instr # a3 = addr of instr
  147.         movem.l d3/d5,-(sp) ;All right, let's start!!
  148.         movea.l    mmd_smplarr(a6),a0
  149.         add.w    d3,d3            ;d3 = instr.num << 2
  150.         add.w    d3,d3
  151.         move.l    0(a0,d3.w),d5        ;get address of instrument
  152.         beq.w    retsn28
  153. inmem8:        add.b    msng_playtransp(a4),d1    ;add play transpose
  154.         add.b    inst_strans(a3),d1    ;and instr. transpose
  155.         tst.b    inst_midich(a3)
  156.         bne.w    retsn28        ;MIDI
  157.         clr.b    trk_vibroffs(a5)    ;clr vibrato offset
  158.         move.l    d5,a0
  159.         subq.b    #1,d1
  160.         tst.w    4(a0)
  161.         bmi.w    retsn28        ;Synth
  162. tlwtst08:    tst.b    d1
  163.         bpl.s    notenot2low8
  164.         add.b    #12,d1    ;note was too low, octave up
  165.         bra.s    tlwtst08
  166. notenot2low8:    cmp.b    #62,d1
  167.         ble.s    endpttest8
  168.         sub.b    #12,d1    ;note was too high, octave down
  169. endpttest8:    bsr.w    getinsdata
  170.         movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  171.         move.l    d0,(a1)        ;put it in ac_ptr
  172.         cmp.w    #1,d3
  173.         bhi.s    repeat8
  174.  
  175.         tst.b    trk_split(a5)
  176.         beq.s    pn8_nosplit0
  177.         add.l    d1,d0
  178.         subq.l    #1,d0
  179.         clr.l    ac_rest(a1)
  180.         move.l    d0,ac_end(a1)
  181.         bra.s    retsn18
  182. pn8_nosplit0    lsr.l    #1,d1
  183.         move.w    d1,ac_len(a1)
  184.         move.l    #zerodata,ac_rest(a1)
  185.         move.w    #1,ac_end(a1)
  186.         bra.s    retsn18
  187.  
  188. repeat8:    tst.b    trk_split(a5)
  189.         bne.s    pn8_split1
  190.         tst.w    d2
  191.         beq.s    begin08        ;rep. start < 2
  192.         move.w    d2,ac_len(a1)    ;move repeat to hardware
  193.         bra.s    beginn08
  194. begin08:    move.w    d3,ac_len(a1)
  195. beginn08:    add.l    d2,d2        ;shift
  196.         add.l    d2,d0        ;d0 = starting address of repeat
  197.         move.l    d0,ac_rest(a1)    ;remember rep. start
  198.         move.w    d3,ac_end(a1)    ;remember rep. length
  199.         bra.s    retsn18
  200. pn8_split1    add.l    d2,d2        ;shift
  201.         add.l    d3,d3
  202.         add.l    d2,d0
  203.         move.l    d0,ac_rest(a1)
  204.         add.l    d3,d0
  205.         subq.l    #1,d0
  206.         move.l    d0,ac_end(a1)
  207.         
  208. retsn18:    move.w    d5,ac_per(a1)    ;getinsdata puts period to d5
  209.         move.w    d5,trk_prevper(a5)
  210. retsn28:    movem.l    (sp)+,d3/d5
  211.         rts
  212.  
  213. t038:        ds.b    20
  214.         dc.l    track0hw
  215.         ds.b    64+20
  216.         dc.l    track1hw
  217.         ds.b    64+20
  218. t238        dc.l    track2hw
  219.         ds.b    64+20
  220.         dc.l    track3hw
  221.         ds.b    64
  222. t4158:        ds.b    20
  223.         dc.l    track4hw
  224.         ds.b    64+20
  225.         dc.l    track5hw
  226.         ds.b    64+20
  227. t6158        dc.l    track6hw
  228.         ds.b    64+20
  229.         dc.l    track7hw
  230.         ds.b    64
  231.         
  232. trackdata8:    dc.l    t038,t038+T03SZ,t038+2*T03SZ,t038+3*T03SZ
  233.         dc.l    t4158,t4158+T03SZ,t4158+2*T03SZ,t4158+3*T03SZ
  234.  
  235. _IntHandler8:    movem.l    d2-d7/a2-a5,-(sp)
  236. ; ================ 8 channel handling (buffer swap) ======
  237.         lea    trksplit(pc),a2
  238.         move.w    #800,d0
  239.         not.b    whichbuff    ;swap buffer
  240.         bne.s    usebuff1
  241.         tst.b    (a2)+
  242.         beq.s    tnspl0
  243.         move.l    a1,$a0(a0)
  244. tnspl0        lea    800(a1),a5
  245.         tst.b    (a2)+
  246.         beq.s    tnspl1
  247.         move.l    a5,$b0(a0)
  248. tnspl1        adda.w    d0,a5
  249.         tst.b    (a2)+
  250.         beq.s    tnspl2
  251.         move.l    a5,$c0(a0)
  252. tnspl2        adda.w    d0,a5
  253.         tst.b    (a2)
  254.         beq.s    buffset
  255.         move.l    a5,$d0(a0)
  256.         bra.s    buffset
  257. usebuff1:    lea    400(a1),a1
  258.         tst.b    (a2)+
  259.         beq.s    tnspl0b
  260.         move.l    a1,$a0(a0)
  261. tnspl0b        lea    800(a1),a5
  262.         tst.b    (a2)+
  263.         beq.s    tnspl1b
  264.         move.l    a5,$b0(a0)
  265. tnspl1b        adda.w    d0,a5
  266.         tst.b    (a2)+
  267.         beq.s    tnspl2b
  268.         move.l    a5,$c0(a0)
  269. tnspl2b        tst.b    (a2)
  270.         beq.s    buffset
  271.         adda.w    d0,a5
  272.         move.l    a5,$d0(a0)
  273. buffset:    move.w    #1<<7,$9c(a0)    ;clear interrupt
  274. ; ============== fill buffers ============
  275.         moveq    #0,d4        ;mask for DMA
  276.         move.l    #3719168,d3
  277.         subq.l    #3,a2        ;a2 = trksplit(pc)
  278.         lea    track0hw(pc),a6
  279.         tst.b    (a2)+
  280.         bne.s    tspl0c
  281.         bsr.w    pushregs
  282.         bra.s    tnspl0c
  283. tspl0c        bsr.s    fillbuf
  284. tnspl0c        adda.w    #400,a1
  285.         lea    track1hw(pc),a6
  286.         tst.b    (a2)+
  287.         bne.s    tspl1c
  288.         bsr.w    pushregs
  289.         bra.s    tnspl1c
  290. tspl1c        bsr.s    fillbuf
  291. tnspl1c        adda.w    #400,a1
  292.         lea    track2hw(pc),a6
  293.         tst.b    (a2)+
  294.         bne.s    tspl2c
  295.         bsr.w    pushregs
  296.         bra.s    tnspl2c
  297. tspl2c        bsr.s    fillbuf
  298. tnspl2c        adda.w    #400,a1
  299.         lea    track3hw(pc),a6
  300.         tst.b    (a2)
  301.         bne.s    tspl3c
  302.         bsr.w    pushregs
  303.         bra.w    do_play8
  304. tspl3c        bsr.s    fillbuf
  305.         bra.w    do_play8
  306. ; ==============================================================
  307. ; This is the magical routine which actually mixes the voices.
  308. ; ==============================================================
  309. ;calculate channel A period
  310. fillbuf:    move.l    d3,d7
  311.         move.w    ac_per(a6),d6
  312.         beq.s    setpzero0
  313.         move.l    d7,d2
  314.         divu     d6,d2
  315.         moveq    #0,d1
  316.         move.w    d2,d1
  317.         add.l    d1,d1
  318.         add.l    d1,d1
  319. ;get channel A addresses
  320.         move.l    ac_end(a6),a5
  321.         move.l    (a6),d0
  322.         beq.s    setpzero0
  323. chA_dfnd    move.l    d0,a3    ;a3 = start address, a5 = end address
  324. ;calc bytes before end
  325.         mulu    #1600,d2
  326.         clr.w    d2
  327.         swap    d2
  328. ; d2 = # of bytes/fill
  329.         add.l    a3,d2    ;d2 = end position after this fill
  330.         sub.l    a5,d2    ;subtract sample end
  331.         bmi.s    norestart0
  332.         move.l    ac_rest(a6),d0
  333.         beq.s    rst0end
  334.         move.l    d0,(a6)
  335.         move.l    d0,a3
  336.         bra.s    norestart0
  337. rst0end        clr.l    (a6)
  338. setpzero0    lea    zerodata(pc),a3
  339.         moveq    #0,d1
  340. norestart0
  341. ;channel B period
  342.         move.w    SIZE4TRKHW+ac_per(a6),d6
  343.         beq.s    setpzero0b
  344.         divu    d6,d7
  345.         moveq    #0,d2
  346.         move.w    d7,d2
  347.         add.l    d2,d2
  348.         add.l    d2,d2
  349. ;channel B addresses
  350.         move.l    SIZE4TRKHW+ac_end(a6),a5
  351.         move.l    SIZE4TRKHW(a6),d0
  352.         beq.s    setpzero0b
  353.         move.l    d0,a4
  354.         mulu    #1600,d7
  355.         clr.w    d7
  356.         swap    d7
  357.         add.l    a4,d7
  358.         sub.l    a5,d7
  359.         bmi.s    norestart0b
  360.         move.l    SIZE4TRKHW+ac_rest(a6),d0
  361.         beq.s    rst0endb
  362.         move.l    d0,SIZE4TRKHW(a6)
  363.         move.l    d0,a4
  364.         bra.s    norestart0b
  365. rst0endb    clr.l    SIZE4TRKHW(a6)
  366. setpzero0b    lea    zerodata(pc),a4
  367.         moveq    #0,d2
  368. norestart0b    moveq    #0,d6
  369.         moveq    #0,d7
  370. ; DBF could have be used (this'd be *much* shorter), but for absolutely
  371. ; maximum speed, I haven't used it here.
  372.         REPT    400
  373.         swap    d6
  374.         swap    d7
  375.         move.b    0(a3,d6.w),d0
  376.         add.b    0(a4,d7.w),d0
  377.         move.b    d0,(a1)+
  378.         swap    d6
  379.         swap    d7
  380.         add.l    d1,d6
  381.         add.l    d2,d7
  382.         ENDR
  383.         clr.w    d6
  384.         clr.w    d7
  385.         swap    d6
  386.         swap    d7
  387.         add.l    d6,(a6)
  388.         add.l    d7,SIZE4TRKHW(a6)
  389.         rts
  390. ; ========== this channel is not splitted
  391. pushregs    move.l    ac_rhw(a6),a3        ;address of real hardware
  392.         move.w    ac_per(a6),ac_per(a3)    ;push new period
  393.         move.l    (a6),d0    ;ac_ptr
  394.         beq.s    pregs_nonewp
  395.         move.w    ac_mask(a6),d1
  396.         move.w    d1,$96(a0)    ;stop DMA of curr. channel
  397.         or.w    d1,d4
  398.         clr.l    (a6)+
  399.         move.l    d0,(a3)+    ;to real ac_ptr
  400.         move.w    (a6),(a3)    ;push ac_len
  401. pregs_nonewp    rts
  402. ; ========== should we start DMA of non-splitted channels?
  403. do_play8    tst.w    d4
  404.         beq.s    do_play8_b    ;no.
  405.         bsr.w    _Wait1line
  406.         bset    #15,d4
  407.         move.w    d4,$96(a0)
  408.         bsr.w    _Wait1line
  409.         lsr.b    #1,d4
  410.         bcc.s    plr_nos8dma0
  411.         move.l    track0hw+ac_rest(pc),$a0(a0)
  412.         move.w    track0hw+ac_end(pc),$a4(a0)
  413. plr_nos8dma0    lsr.b    #1,d4
  414.         bcc.s    plr_nos8dma1
  415.         move.l    track1hw+ac_rest(pc),$b0(a0)
  416.         move.w    track1hw+ac_end(pc),$b4(a0)
  417. plr_nos8dma1    lsr.b    #1,d4
  418.         bcc.s    plr_nos8dma2
  419.         move.l    track2hw+ac_rest(pc),$c0(a0)
  420.         move.w    track2hw+ac_end(pc),$c4(a0)
  421. plr_nos8dma2    lsr.b    #1,d4
  422.         bcc.s    do_play8_b
  423.         move.l    track3hw+ac_rest(pc),$d0(a0)
  424.         move.w    track3hw+ac_end(pc),$d4(a0)
  425. ; ========== player starts here...
  426. do_play8_b    move.l    _module8(pc),d0
  427.         beq.w    plr_exit8
  428.         movea.l    d0,a6
  429.         move.l    mmd_songinfo(a6),a4
  430.         moveq    #0,d3
  431.         move.b    mmd_counter(a6),d3
  432.         addq.b    #1,d3
  433.         cmp.b    msng_tempo2(a4),d3
  434.         bge.s    plr_pnewnote8    ;play new note
  435.         move.b    d3,mmd_counter(a6)
  436.         bne.w    nonewnote8    ;do just fx
  437. ; --- new note!! first get address of current block
  438. plr_pnewnote8:    clr.b    mmd_counter(a6)
  439. ; --- now start to play it
  440.         move.w    mmd_pblock(a6),d0
  441.         movea.l    mmd_blockarr(a6),a0
  442.         add.w    d0,d0
  443.         add.w    d0,d0
  444.         movea.l    0(a0,d0.w),a2    ;block...
  445.         lea    numtracks(pc),a0
  446.         move.b    (a2)+,1(a0)    ;->numtracks+1
  447.         move.b    (a2)+,3(a0)    ;->numlines+1
  448.         move.w    mmd_pline(a6),d0
  449.         move.w    d0,d1
  450.         add.w    d0,d0    ;d0 * 2
  451.         add.w    d1,d0    ;+ d0 = d0 * 3
  452.         mulu    (a0),d0
  453.         adda.w    d0,a2
  454.         cmp.w    #8,(a0)
  455.         ble.s    plr_noover8
  456.         move.w    #8,(a0)
  457. plr_noover8    moveq    #0,d7        ;number of track
  458.         pea    trackdata8(pc)
  459. plr_loop08:    moveq    #0,d5
  460.         move.l    (sp),a1
  461.         movea.l    (a1)+,a5    ;get address of this track's struct
  462.         move.l    a1,(sp)
  463. ; ---------------- get the note numbers
  464.         move.b    (a2)+,d5    ;get the number of this note
  465.         move.b    (a2)+,d6    ;and the 4 numbers containing fx
  466.         move.b    (a2)+,trk_cmdqual(a5)    ;get & save the fx numbers
  467. ; ---------------- clear some instrument # flags
  468.         moveq    #0,d4        ;d4 is a flag: if set, instr. is
  469.         moveq    #0,d3        ;in range G-V. If clr, it's 1-F.
  470. ; ---------------- and set them, if needed
  471.         bclr    #7,d5        ;d3 is also a flag. If it's set,
  472.         sne    d4        ;the instr. is in range 10 - 1V
  473.         bclr    #6,d5
  474.         sne    d3
  475. ; ---------------- check if there's an instrument number
  476.         move.b    d6,d0
  477.         and.w    #$f0,d0        ;d0 now contains only the # of instr
  478.         bne.s    instnum8    ;instrument number is not 0
  479.         tst.b    d4        ;maybe it's G (instr. #0, d4 set)
  480.         bne.s    instnum8    ;yes, it really was G!!
  481.         tst.b    d3
  482.         beq.s    noinstnum8    ;it wasn't 10 - 1V either..
  483. ; ---------------- if there was, GET IT!!
  484. instnum8:    lsr.b    #4,d0        ;shift it right to get number 0-F
  485.         tst.b    d4
  486.         beq.s    nogtov28
  487.         add.w    #16,d0        ;if G-V, add 16 to the number
  488. nogtov28:    tst.b    d3
  489.         beq.s    no10to1v8
  490.         add.w    #32,d0
  491. ; ---------------- finally, save the number
  492. no10to1v8:    subq.b    #1,d0
  493.         move.b    d0,trk_previnstr(a5) ;remember instr. number!
  494.         lea    holdvals(pc),a0
  495.         move.b    0(a0,d0.w),trk_inithold(a5)    ;hold
  496. ; ---------------- get the pointer of data's of this sample in Song-struct
  497.         lsl.w    #3,d0
  498.         lea    0(a4,d0.w),a3
  499.         move.l    a3,trk_previnstra(a5)
  500. ; ---------------- set volume to 64
  501.         movea.l    trk_audioaddr(a5),a0
  502.         movea.l    ac_vol(a0),a0    ;ptr to volume hardware register
  503.         moveq    #64,d1
  504.         move.b    d1,(a0)
  505.         move.b    d1,trk_prevvol(a5)
  506. ; ---------------- remember the some values of this instrument
  507.         move.b    inst_strans(a3),trk_stransp(a5)    ;rem. transpose
  508.         moveq    #0,d0
  509. ; ---------------- check the commands
  510. noinstnum8    and.b    #$0f,d6        ;now check only the effect part
  511.         move.b    d6,trk_cmd(a5)    ;save the effect number
  512.         beq.w    plr_nocmd8    ;no effect
  513.         move.b    d6,d0
  514.         move.b    trk_cmdqual(a5),d6    ;get qualifier...
  515. ; ---------------- there was a command (effect), but which one??
  516.         cmp.b    #$0f,d0        ;yes effect...is it Tempo???
  517.         bne.s    not0f8        ;not Tempo
  518. ; ---------------- it was tempo (F)
  519.         tst.b    d6        ;test effect qual..
  520.         beq.s    fx0fchgblck8    ;if effect qualifier (last 2 #'s)..
  521.         cmp.b    #$f0,d6        ;..is zero, go to next block
  522.         bls.w    plr_nocmd8    ;01 - F0, not supported on 8 channels
  523. ; ---------------- no, it was FFx, something special will happen!!
  524. fx0fspecial8:    cmp.b    #$f2,d6    ; | rest - play | SpecialFX#2: no note..yet
  525.         bne.s    isfxfe8    ;not SpecFX2
  526. ; ---------------- it was FF2, nothing to do now
  527.         move.b    d5,(a5)    ;Yes!!! Save the note number
  528.         moveq    #0,d5    ; clear the number for awhile
  529.         bra.w    plr_nocmd8
  530. isfxfe8:    cmp.b    #$fe,d6
  531.         bne.s    notcmdfe8
  532. ; ---------------- it was FFE, stop playing
  533.         clr.w    mmd_pstate(a6)
  534.         bsr.w    _End8Play
  535.         addq.l    #4,sp
  536.         bra.w    plr_exit8
  537. notcmdfe8:    cmp.b    #$fd,d6 ;change period
  538.         bne.s    isfxff8
  539. ; ---------------- FFD, change the period, don't replay the note
  540.         movea.l    trk_periodtbl(a5),a0    ;period table
  541.         subq.b    #1,d5    ;sub 1 to make "real" note number
  542.         bmi.w    plr_endloop08    ;under zero, do nothing
  543.         add.b    d5,d5
  544.         move.w    0(a0,d5.w),d0 ;get the period
  545.         movea.l    trk_audioaddr(a5),a0
  546.         move.w    d0,ac_per(a0) ;push the period
  547.         moveq    #0,d5 ;and clear it so that it won't be replayed
  548.         bra.w    plr_nocmd8    ;done!!
  549. isfxff8:    cmp.b    #$ff,d6        ;note off??
  550.         bne.w    plr_nocmd8
  551.         move.w    d7,d0
  552.         bsr.w    _ChannelO8
  553.         bra.w    plr_nocmd8
  554. ; ---------------- F00, called Pattern Break in ST
  555. fx0fchgblck8:    addq.b    #1,nextblock    ;next block????...YES!!!! (F00)
  556.         bra.w    plr_nocmd8
  557. ; ---------------- was not Fxx, then it's something else!!
  558. not0f8:        cmp.b    #$0c,d0        ;new volume???
  559.         bne.s    not0c8        ;NO!!!!!!!!!!!!!!!!!!!!!!
  560. ; ---------------- change volume
  561.         move.b    d6,d0
  562.         btst    #4,msng_flags(a4)    ;look at flags
  563.         bne.s    volhex8
  564.         lsr.b    #4,d0        ;get number from left
  565.         mulu    #10,d0        ;number of tens
  566.         move.b    d6,d1        ;get again
  567.         and.b    #$0f,d1        ;this time don't get tens
  568.         add.b    d1,d0        ;add them
  569. volhex8        cmp.b    #64,d0
  570.         bhi.s    plr_nocmd8
  571.         movea.l    trk_audioaddr(a5),a0
  572.         movea.l    ac_vol(a0),a0
  573.         move.b    d0,(a0)
  574.         move.b    d0,trk_prevvol(a5)
  575.         bra.s    plr_nocmd8
  576. ; ---------------- tempo2 change??
  577. not0c8:        cmp.b    #$09,d0
  578.         bne.s    not098
  579.         and.b    #$1F,d6
  580.         bne.s    fx9chk8
  581.         moveq    #$20,d6
  582. fx9chk8        move.b    d6,msng_tempo2(a4)
  583.         bra.s    plr_nocmd8
  584. ; ---------------- note off time set??
  585. not098:        cmp.b    #$08,d0
  586.         bne.s    not088
  587.         and.b    #$0f,d6        ; extract right only
  588.         move.b    d6,trk_inithold(a5)    ;right = hold
  589.         bra.s    plr_nocmd8
  590. ; ---------------- cmd Bxx, "position jump", like Goto, yäk!!
  591. not088        cmp.b    #$0b,d0
  592.         bne.s    not0b8
  593.         move.w    d6,d0
  594.         and.w    #$00ff,d0
  595.         cmp.w    msng_songlen(a4),d0    ;test the song length
  596.         bhi.s    plr_nocmd8
  597.         move.w    d0,mmd_pseqnum(a6)
  598.         st    nextblock    ; = 1
  599.         bra.s    plr_nocmd8
  600. ; ---------------- try portamento (3)
  601. not0b8:        cmp.b    #$03,d0
  602.         bne.s    plr_nocmd8
  603.         subq.b    #1,d5        ;subtract note number
  604.         bpl.s    plr_fx3note8    ;there's a note...
  605.         tst.b    d6        ;qual??
  606.         beq.s    plr_endloop08    ;0 -> do nothing
  607.         bra.s    plr_setfx3spd8    ;not 0 -> set new speed
  608. plr_fx3note8:    movea.l    trk_periodtbl(a5),a0
  609.         add.b    msng_playtransp(a4),d5    ;play transpose
  610.         add.b    trk_stransp(a5),d5 ;and instrument transpose
  611.         bmi.s    plr_endloop08    ;again.. too low
  612.         add.w    d5,d5
  613.         move.w    0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
  614. plr_setfx3spd8:    move.b    d6,trk_prevportspd(a5)    ;remember size
  615.         moveq    #0,d5    ;don't play this one
  616. ; ---------------- everything is checked now: play or not to play??
  617. plr_nocmd8:    tst.b    d5    ;Now we'll check if we have to play a note
  618.         beq.s    plr_endloop08    ;no.
  619. ; ---------------- we decided to play
  620.         move.b    d5,(a5)
  621.         move.w    d7,d0
  622.         move.w    d5,d1
  623.         moveq    #0,d2
  624.         moveq    #0,d3
  625.         move.b    trk_previnstr(a5),d3    ;instr #
  626.         movea.l    trk_previnstra(a5),a3    ;instr data address
  627. ; ---------------- does this instrument have holding??
  628.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  629.         bne.s    plr_holdok8    ;not 0 -> OK
  630.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  631. ; ---------------- and finally:
  632. plr_holdok8:    bsr    _PlayNote8    ;play it!!!!!!!!!!!
  633. ; ---------------- end of loop: handle next track, or quit
  634. plr_endloop08:    addq.b    #1,d7
  635.         cmp.w    numtracks(pc),d7
  636.         blt.w    plr_loop08
  637.         addq.l    #4,sp        ;trackdata8
  638.  
  639. ; and advance song pointers
  640.         move.w    mmd_pline(a6),d1    ;pline
  641.         addq.w    #1,d1            ;very important!!! advance line!!
  642.         cmp.w    numlines(pc),d1        ;important too!!! advance block??
  643.         bgt.s    plr_chgblock8        ;yes!!!
  644.         tst.b    nextblock        ;command F00 ??
  645.         beq.s    plr_nochgblock8        ;no, don't change block
  646. plr_chgblock8:    moveq    #0,d1            ;clear line number
  647.         tst.w    mmd_pstate(a6)        ;play block or play song
  648.         bpl.s    plr_nonewseq8        ;play block only...
  649.         move.w    mmd_pseqnum(a6),d0    ;get play sequence number
  650.         tst.b    nextblock
  651.         bmi.s    plr_noadvseq8        ;Bxx sets nextblock to 0xff (= neg)
  652.         addq.w    #1,d0            ;advance sequence number
  653. plr_noadvseq8:    cmp.w    msng_songlen(a4),d0     ;is this the highest seq number??
  654.         blt.s    plr_notagain8        ;no.
  655.         moveq    #0,d0            ;yes: play song again
  656.         moveq    #0,d1            ;...forever!!!
  657. plr_notagain8:    move.b    d0,mmd_pseqnum+1(a6)    ;remember new playseq-#
  658.         lea    msng_playseq(a4),a0    ;offset of sequence table
  659.         move.b    0(a0,d0.w),d0        ;get number of the block
  660.         cmp.b    msng_numblocks+1(a4),d0    ;beyond last block??
  661.         blt.s    plr_nolstblk8        ;no..
  662.         moveq    #0,d0            ;play block 0
  663. plr_nolstblk8:    move.b    d0,mmd_pblock+1(a6)    ;store pblock
  664. plr_nonewseq8:    clr.b    nextblock        ;clear this if F00 set it
  665. plr_nochgblock8    move.w    d1,mmd_pline(a6)    ;set new pline
  666.  
  667.         movea.l    mmd_blockarr(a6),a0
  668.         move.w    mmd_pblock(a6),d0    ;pblock
  669.         add.w    d0,d0
  670.         add.w    d0,d0
  671.         movea.l    0(a0,d0.w),a2        ;block...
  672.         move.b    (a2),d7            ;# of tracks
  673.         move.w    mmd_pline(a6),d0    ;play line
  674.         move.w    d0,d1
  675.         add.w    d0,d0    ;d0 * 2
  676.         add.w    d1,d0    ;+ d0 = d0 * 3
  677.         mulu    d7,d0
  678.         lea    2(a2,d0.w),a2
  679.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  680.         lea    trackdata8(pc),a0
  681.         cmp.b    #8,d7
  682.         ble.s    plr_noov8b
  683.         moveq    #8,d7
  684. plr_noov8b    subq.b    #1,d7
  685. plr_chkhold8:    movea.l    (a0)+,a1        ;track data
  686.         tst.b    trk_noteoffcnt(a1)    ;hold??
  687.         bmi.s    plr_holdend8        ;no.
  688.         move.b    (a2),d1            ;get the 1st byte..
  689.         bne.s    plr_hold18
  690.         move.b    1(a2),d1
  691.         and.b    #$f0,d1
  692.         beq.s    plr_holdend8        ;don't hold
  693.         bra.s    plr_hold28
  694. plr_hold18:    and.b    #$3f,d1            ;note??
  695.         beq.s    plr_hold28        ;no, cont hold..
  696.         move.b    1(a2),d1
  697.         and.b    #$0f,d1            ;get cmd
  698.         subq.b    #3,d1            ;is there command 3 (slide)
  699.         bne.s    plr_holdend8        ;no -> end holding
  700. plr_hold28:    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  701. plr_holdend8:    addq.l    #3,a2            ;next note
  702.         dbf    d7,plr_chkhold8
  703.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  704.         bne.w    plr_endfx8        ;yes, no effects this time...
  705.         moveq    #0,d3            ;counter = 0!!!
  706. nonewnote8:
  707. ;    *********************** This code produces the effects **
  708.         moveq    #0,d7    ;clear track count
  709.         moveq    #0,d6
  710.         lea    trackdata8(pc),a2
  711. plr_loop18:    movea.l    (a2)+,a5
  712.         moveq    #0,d5
  713.         moveq    #0,d4
  714.         move.b    trk_cmd(a5),d6    ;get the fx number
  715.         move.b    trk_cmdqual(a5),d4    ;and the last 2 #'s
  716.         tst.b    trk_noteoffcnt(a5)
  717.         bmi.s    plr_nowaitoff8
  718.         subq.b    #1,trk_noteoffcnt(a5)
  719.         bpl.s    plr_nowaitoff8
  720.         movea.l    trk_audioaddr(a5),a1
  721.         clr.w    ac_per(a1)    ;if ac_per is 0, sound'll be stopped
  722. plr_nowaitoff8:    add.b    d6,d6    ;* 2
  723.         move.w    fx_table8(pc,d6.w),d0
  724.         jmp    fxs8(pc,d0.w)
  725. fx_table8:    dc.w    fx_008-fxs8,fx_018-fxs8,fx_028-fxs8,fx_038-fxs8,fx_048-fxs8
  726.         dc.w    fx_058-fxs8,fx_xx8-fxs8,fx_xx8-fxs8,fx_xx8-fxs8,fx_xx8-fxs8
  727.         dc.w    fx_0a8-fxs8,fx_xx8-fxs8,fx_0c8-fxs8,fx_0d8-fxs8,fx_xx8-fxs8
  728.         dc.w    fx_0f8-fxs8
  729. fxs8:
  730. ;    **************************************** Effect 01 ******
  731. fx_018:        sub.w    d4,trk_prevper(a5)    ;slide it up!!!
  732.         move.w    trk_prevper(a5),d5
  733.         cmp.w    #113,d5        ;too high???
  734.         bge    newvals8
  735.         move.w    #113,d5        ;yes, too high!!!
  736.         move.w    d5,trk_prevper(a5)
  737.         bra    newvals8
  738. ;    **************************************** Effect 02 ******
  739. fx_028:        add.w    d4,trk_prevper(a5)    ;slide it down!!!!!!!!!
  740.         move.w    trk_prevper(a5),d5
  741.         bra.w    newvals8
  742. ;    **************************************** Effect 00 ******
  743. fx_008:        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio!!
  744.         beq.w    endl8
  745.         move.l    d3,d0
  746.         divu    #3,d0
  747.         swap    d0
  748.         tst.w    d0
  749.         bne.s    fx_arp128
  750.         and.b    #$0f,d4
  751.         add.b    (a5),d4
  752.         bra.s    fx_doarp8
  753. fx_arp128:    subq.b    #1,d0
  754.         bne.s    fx_arp28
  755.         lsr.b    #4,d4
  756.         add.b    (a5),d4
  757.         bra.s    fx_doarp8
  758. fx_arp28:    move.b    (a5),d4
  759. fx_doarp8:    subq.b    #1,d4        ;-1 to make it 0 - 127
  760.         add.b    msng_playtransp(a4),d4    ;add play transpose
  761.         add.b    trk_stransp(a5),d4    ;add instrument transpose
  762.         add.b    d4,d4        ;shift to make index for UWORD
  763.         movea.l    trk_periodtbl(a5),a1
  764.         move.w    0(a1,d4.w),d5
  765.         bra.w    newvals8
  766. ;    **************************************** Effect 0D/0A ***
  767. fx_0a8:
  768. fx_0d8:        move.b    d4,d1
  769.         move.b    trk_prevvol(a5),d0    ;move previous vol to d0
  770.         and.b    #$f0,d1
  771.         bne.s    crescendo8
  772.         sub.b    d4,d0    ;sub from prev. vol
  773.         bpl.s    novolund08
  774.         moveq    #0,d0    ;volumes under zero not accepted!!!
  775. novolund08:    move.b    d0,trk_prevvol(a5)    ;put new vol back
  776.         bra.s    setvc8
  777. crescendo8:    lsr.b    #4,d1
  778.         add.b    d1,d0
  779.         cmp.b    #64,d0
  780.         ble.s    novolover648
  781.         moveq    #64,d0
  782. novolover648:    move.b    d0,trk_prevvol(a5)
  783. setvc8        movea.l    trk_audioaddr(a5),a0
  784.         movea.l    ac_vol(a0),a0
  785.         move.b    d0,(a0)
  786.         bra.w    fx_xx8
  787. ;    **************************************** Effect 05 ******
  788. fx_058:        move.w    trk_prevper(a5),d5 ;this is very simple: get the old period
  789.         cmp.b    #3,d3        ;and..
  790.         bge.w    newvals8        ;if counter < 3
  791.         sub.w    d4,d5    ;subtract effect qualifier
  792.         bra.w    newvals8
  793. ;    **************************************** Effect 0C ******
  794. fx_0c8:        movea.l    trk_audioaddr(a5),a0
  795.         movea.l    ac_vol(a0),a0    ;ptr to volume hardware register
  796.         move.b    trk_prevvol(a5),(a0)
  797.         bra.w    endl8
  798. ;    **************************************** Effect 03 ******
  799. fx_038:        move.w    trk_porttrgper(a5),d0    ;d0 = target period
  800.         beq.w    newvals8    ;no target period specified
  801.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  802.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  803.         cmp.w    d0,d1
  804.         bhi.s    subper8    ;curr. period > target period
  805.         add.w    d4,d1    ;add the period
  806.         cmp.w    d0,d1
  807.         bge.s    targreached8
  808.         bra.s    targnreach8
  809. subper8:    sub.w    d4,d1    ;subtract
  810.         cmp.w    d0,d1    ;compare current period to target period
  811.         bgt.s    targnreach8
  812. targreached8:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  813.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  814. targnreach8:    move.w    d1,trk_prevper(a5)
  815.         move.w    d1,d5
  816.         bra.w    newvals8
  817. ;    **************************************** Effect 04 ******
  818. fx_048:        tst.b    d4
  819.         beq.s    nonvib8
  820.         move.b    d4,trk_vibrspdsz(a5)
  821. nonvib8:    move.b    trk_vibroffs(a5),d0
  822.         lsr.b    #2,d0
  823.         and.w    #$1f,d0
  824.         moveq    #0,d1
  825.         lea    sinetable(pc),a0
  826.         move.b    0(a0,d0.w),d5
  827.         ext.w    d5
  828.         move.b    trk_vibrspdsz(a5),d0
  829.         and.w    #$000f,d0
  830.         muls    d0,d5
  831.         asr.w    #5,d5
  832.         add.w    trk_prevper(a5),d5
  833.         move.b    trk_vibrspdsz(a5),d0
  834.         lsr.b    #3,d0
  835.         and.b    #$3e,d0
  836.         add.b    d0,trk_vibroffs(a5)
  837.         bra.w    newvals8
  838. ;    **************************************** Effect 0F ******
  839. fx_0f8:        cmp.b    #$f1,d4
  840.         bne.s    no0ff18
  841.         cmp.b    #3,d3
  842.         bne.w    endl8
  843.         bra.s    playfxnote8
  844. no0ff18:    cmp.b    #$f2,d4
  845.         bne.s    no0ff28
  846.         cmp.b    #3,d3
  847.         bne.w    endl8
  848.         bra.s    playfxnote8
  849. no0ff28:    cmp.b    #$f3,d4
  850.         bne.s    no0ff38
  851.         move.b    d3,d0
  852.         and.b    #2+4,d0        ;is 2 or 4
  853.         beq.w    endl8
  854. playfxnote8:    move.w    d7,d0        ;track # to d0...
  855.         moveq    #0,d1
  856.         move.b    (a5),d1        ;get note # of previous note
  857.         beq.s    endl8
  858.         move.w    d3,-(sp)
  859.         moveq    #0,d3
  860.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  861.         movea.l    trk_previnstra(a5),a3
  862.         bsr    _PlayNote8
  863.         move.w    (sp)+,d3
  864.         bra.s    endl8
  865. no0ff38:    cmp.b    #$f8,d4        ;f8 = filter off
  866.         beq.s    plr_filteroff8
  867.         cmp.b    #$f9,d4        ;f9 = filter on
  868.         bne.s    endl8
  869.         bclr    #1,$bfe001
  870.         bra.s    endl8
  871. plr_filteroff8:    bset    #1,$bfe001
  872.         bra.s    endl8
  873. ;    *********************************************************
  874. newvals8    tst.w    d5    ;now: do the effects!!!
  875.         beq.s    fx_xx8
  876.         movea.l    trk_audioaddr(a5),a1    ;get channel address
  877.         move.w    d5,ac_per(a1)    ;push period
  878. fx_xx8:
  879. endl8:        addq.b    #1,d7    ;increment channel number
  880.         cmp.w    numtracks(pc),d7    ;all channels done???
  881.         blt.w    plr_loop18    ;not yet!!!
  882. plr_endfx8:
  883. plr_exit8:    movem.l    (sp)+,d2-d7/a2-a5
  884.         moveq    #1,d0
  885.         rts
  886.  
  887. zerodata    dc.w    0
  888.  
  889. whichbuff:    dc.w    0
  890.  
  891. ; here are the "hardware" registers
  892.  
  893. track0hw:    dc.l    0,0,$dff0a9,0,0
  894.         dc.w    $0001,$df,$f0a0
  895. track1hw:    dc.l    0,0,$dff0b9,0,0
  896.         dc.w    $0002,$df,$f0b0
  897. track2hw:    dc.l    0,0,$dff0c9,0,0
  898.         dc.w    $0004,$df,$f0c0
  899. track3hw:    dc.l    0,0,$dff0d9,0,0
  900.         dc.w    $0008,$df,$f0d0
  901. track4hw:    dc.l    0,0,$dff0a9,0,0
  902.         dc.w    0,0,0
  903. track5hw:    dc.l    0,0,$dff0b9,0,0
  904.         dc.w    0,0,0
  905. track6hw:    dc.l    0,0,$dff0c9,0,0
  906.         dc.w    0,0,0
  907. track7hw:    dc.l    0,0,$dff0d9,0,0
  908.         dc.w    0,0,0
  909. SIZE4TRKHW    equ    4*$1A
  910.  
  911. audintname:    dc.b    'OctaMED AudioInterrupt',0
  912.         even
  913. audiointerrupt:    dc.w    0,0,0,0,0
  914.         dc.l    audintname,_audiobuff,_IntHandler8
  915. prevaud:    dc.l    0
  916. play8:        dc.b    0
  917. eightrkon:    dc.b    0
  918.  
  919. _Init8chan:    move.l    a6,-(sp)
  920.         move.w    #1<<7,$dff09a
  921.         moveq    #7,d0        ;Audio channel 0 interrupt
  922.         lea    audiointerrupt(pc),a1
  923.         move.l    4,a6
  924.         jsr    -$a2(a6)    ;SetIntVector()
  925.         move.l    d0,prevaud
  926.         st    eightrkon
  927.         move.l    (sp)+,a6
  928.         rts
  929.  
  930. _Rem8chan:    move.l    a6,-(sp)
  931.         move.b    eightrkon(pc),d0
  932.         beq.s    no8init
  933.         clr.b    eightrkon
  934.         move.w    #1<<7,$dff09a
  935.         moveq    #7,d0
  936.         move.l    prevaud(pc),d0
  937.         beq.s    no8init
  938.         move.l    d0,a1
  939.         move.l    4,a6
  940.         jsr    -$a2(a6)
  941. no8init        move.l    (sp)+,a6
  942.         rts
  943.  
  944. _Start8Play:    lea    _audiobuff,a0
  945.         move.w    #799,d1
  946. clrbuffloop:    clr.l    (a0)+        ;clear track buffers
  947.         dbf    d1,clrbuffloop
  948.         lea    $dff000,a0
  949.         move.w    #227,d1
  950.         move.w    d1,$a6(a0)
  951.         move.w    d1,$b6(a0)
  952.         move.w    d1,$c6(a0)
  953.         move.w    d1,$d6(a0)
  954.         move.w    #200,d1
  955.         move.w    d1,$a4(a0)
  956.         move.w    d1,$b4(a0)
  957.         move.w    d1,$c4(a0)
  958.         move.w    d1,$d4(a0)
  959.         move.l    #_audiobuff,$a0(a0)
  960.         move.l    #_audiobuff+800,$b0(a0)
  961.         move.l    #_audiobuff+1600,$c0(a0)
  962.         move.l    #_audiobuff+2400,$d0(a0)
  963.         moveq    #64,d1
  964.         move.w    d1,$a8(a0)
  965.         move.w    d1,$b8(a0)
  966.         move.w    d1,$c8(a0)
  967.         move.w    d1,$d8(a0)
  968.         clr.b    whichbuff
  969.         movea.l    4,a1
  970.         move.w    #$4000,$9a(a0)
  971.         addq.b    #1,$126(a1)
  972.         lea    track0hw,a1
  973.         moveq    #7,d1
  974. clrtrkloop    clr.l    (a1)
  975.         clr.w    ac_per(a1)
  976.         adda.w    #SIZE4TRKHW/4,a1
  977.         dbf    d1,clrtrkloop
  978.         move.w    #$F,$dff096    ;audio DMA off
  979.         bsr.w    _Wait1line    ;wait until all stopped
  980.         st    play8
  981.         move.w    #$8080,$9a(a0)
  982.         move.w    chdmamask(pc),d1
  983.         bset    #15,d1
  984.         move.w    d1,$96(a0)
  985.         movea.l    4,a1
  986.         subq.b    #1,$126(a1)
  987.         bge.s    x8play
  988.         move.w    #$c000,$9a(a0)
  989. x8play        rts
  990.         
  991. _End8Play:    move.b    play8(pc),d0
  992.         beq.s    noend8play
  993.         move.w    #1<<7,$dff09a
  994.         move.w    #$F,$dff096
  995.         clr.b    play8
  996. noend8play    rts
  997.  
  998. _SetChMode    ;a0 = address of 4 UBYTEs
  999.         movem.l    a2/d2,-(sp)
  1000.         lea    trksplit(pc),a2
  1001.         lea    t038+trk_split(pc),a1
  1002.         moveq    #3,d0
  1003.         moveq    #0,d1
  1004. scm_loop    lsr.b    #1,d1
  1005.         move.b    (a0)+,d2
  1006.         beq.s    scm_split
  1007.         moveq    #0,d2
  1008.         bra.s    scm_nosplit
  1009. scm_split    or.b    #8,d1
  1010.         st    d2
  1011. scm_nosplit    move.b    d2,(a1)
  1012.         move.b    d2,4*T03SZ(a1)
  1013.         lea    T03SZ(a1),a1
  1014.         move.b    d2,(a2)+
  1015.         dbf    d0,scm_loop
  1016.         move.w    d1,chdmamask
  1017.         movem.l    (sp)+,a2/d2
  1018.         rts
  1019.  
  1020. ; *************************************************************************
  1021. ; *************************************************************************
  1022. ; ***********          P U B L I C   F U N C T I O N S          ***********
  1023. ; *************************************************************************
  1024. ; *************************************************************************
  1025.  
  1026.         xdef    _InitModule8,_PlayModule8,_PlayModule82
  1027.         xdef    _InitPlayer8,_RemPlayer8,_StopPlayer8
  1028.         xdef    _ContModule8
  1029.  
  1030. ; *************************************************************************
  1031. ; InitModule8(a0 = module) -- extract expansion data etc.. from the module
  1032. ; *************************************************************************
  1033.  
  1034. _InitModule8:    movem.l    a2-a3/d2,-(sp)
  1035.         move.l    a0,d0
  1036.         beq.s    IM_exit            ;0 => xit
  1037.         lea    holdvals(pc),a2
  1038.         move.l    mmd_expdata(a0),d0    ;expdata...
  1039.         beq.s    IM_clrhlddec        ;none here
  1040.         move.l    d0,a1
  1041.         move.l    4(a1),d0        ;exp_smp
  1042.         beq.s    IM_clrhlddec    ;again.. nothing
  1043.         move.l    d0,a0        ;InstrExt...
  1044.         move.w    8(a1),d2    ;# of entries
  1045.         beq.s    IM_clrhlddec
  1046.         subq.w    #1,d2        ;- 1 (for dbf)
  1047.         move.w    10(a1),d0    ;entry size
  1048. IM_loop1    move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  1049.         adda.w    d0,a0        ;ptr to next InstrExt
  1050.         dbf    d2,IM_loop1
  1051.         bra.s    IM_exit
  1052. IM_clrhlddec    moveq    #31,d0        ;no InstrExt => clear holdvals/decays
  1053. IM_loop2    clr.w    (a2)+
  1054.         dbf    d0,IM_loop2
  1055. IM_exit        movem.l    (sp)+,a2-a3/d2
  1056. PM_end        rts
  1057.  
  1058.  
  1059. ; *************************************************************************
  1060. ; ContModule8(a0 = module) -- continue playing
  1061. ; *************************************************************************
  1062. _ContModule8    bsr.w    _End8Play
  1063.         moveq    #0,d0
  1064.         bra.s    contpoint8
  1065. ; *************************************************************************
  1066. ; PlayModule8(a0 = module)  -- initialize & play it!!
  1067. ; (PlayModule82(a0 = module) -- play module (must be initialized))
  1068. ; *************************************************************************
  1069. _PlayModule8:    st    d0
  1070. contpoint8    movem.l    a0/d0,-(sp)
  1071.         bsr    _InitModule8
  1072.         movem.l    (sp)+,a0/d0
  1073. _PlayModule82:    move.b    audiodevopen(pc),d1
  1074.         beq.s    PM_end        ;resource allocation failure
  1075.         move.l    a0,d1
  1076.         beq.s    PM_end        ;module failure
  1077.         bsr.w    _End8Play
  1078.         clr.l    _module8
  1079.         move.w    _modnum8,d1
  1080.         beq.s    PM_modfound
  1081. PM_nextmod    tst.l    mmd_expdata(a0)
  1082.         beq.s    PM_modfound
  1083.         move.l    mmd_expdata(a0),a1
  1084.         tst.l    (a1)
  1085.         beq.s    PM_modfound        ;no more modules here!
  1086.         move.l    (a1),a0
  1087.         subq.w    #1,d1
  1088.         bgt.s    PM_nextmod
  1089. PM_modfound    movea.l    mmd_songinfo(a0),a1        ;song
  1090.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  1091.         btst    #0,msng_flags(a1)
  1092.         bne.s    PM_filon
  1093.         bset    #1,$bfe001
  1094.         bra.s    PM_filset
  1095. PM_filon    bclr    #1,$bfe001
  1096. PM_filset    tst.b    d0
  1097.         beq.s    PM_noclr
  1098.         clr.l    mmd_pline(a0)
  1099. PM_noclr    move.w    mmd_pseqnum(a0),d1
  1100.         add.w    #msng_playseq,d1
  1101.         move.b    0(a1,d1.w),d1
  1102.         move.b    d1,mmd_pblock+1(a0)
  1103.         move.w    #-1,mmd_pstate(a0)
  1104.         move.l    a0,_module8
  1105.         move.l    mmd_expdata(a0),d0
  1106.         beq.w    _Start8Play
  1107.         movea.l    d0,a0
  1108.         lea    36(a0),a0    ;track split mask
  1109.         bsr    _SetChMode
  1110.         bra.w    _Start8Play
  1111. ; *************************************************************************
  1112. ; InitPlayer8() -- allocate interrupt, audio, serial port etc...
  1113. ; *************************************************************************
  1114. _InitPlayer8:    bsr.s    _AudioInit
  1115.         tst.l    d0
  1116.         bne.s    IP_error
  1117.         rts
  1118. IP_error    bsr.s    _RemPlayer8
  1119.         moveq    #-1,d0
  1120.         rts
  1121. ; *************************************************************************
  1122. ; StopPlayer8() -- stop music
  1123. ; *************************************************************************
  1124. _StopPlayer8:    move.l    _module8(pc),d0
  1125.         beq.s    SP_nomod
  1126.         movea.l    d0,a0
  1127.         clr.w    mmd_pstate(a0)
  1128.         clr.l    _module8
  1129. SP_nomod    bra.w    _End8Play
  1130.  
  1131. ; *************************************************************************
  1132. ; RemPlayer8() -- free interrupt, audio, serial port etc..
  1133. ; *************************************************************************
  1134. _RemPlayer8:    bsr.s    _StopPlayer8
  1135. ;        vvvvvvvvvvvvvvvv  to _AudioRem
  1136. ; *************************************************************************
  1137.  
  1138. _AudioRem:    move.l    a6,-(sp)
  1139.         bsr.w    _Rem8chan
  1140.         movea.l    4,a6
  1141.         tst.b    audiodevopen
  1142.         beq.s    rem2
  1143.         move.w    #$000f,$dff096    ;stop audio DMA
  1144. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  1145.         lea    allocreq(pc),a1
  1146.         jsr    -$1c2(a6)    ;CloseDevice()
  1147.         clr.b    audiodevopen
  1148. rem2:        moveq    #0,d0
  1149.         move.b    sigbitnum(pc),d0
  1150.         bmi.s    rem3
  1151. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  1152.         jsr    -$150(a6)    ;FreeSignal()
  1153.         st    sigbitnum
  1154. rem3:        move.l    (sp)+,a6
  1155.         rts
  1156.  
  1157. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  1158.         moveq    #0,d2
  1159.         movea.l    4,a6
  1160. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  1161.         addq.l    #1,d2
  1162.         moveq    #-1,d0
  1163.         jsr    -$14a(a6)    ;AllocSignal()
  1164.         tst.b    d0
  1165.         bmi.w    initerr
  1166.         move.b    d0,sigbitnum
  1167. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  1168.         lea    allocport(pc),a1
  1169.         move.b    d0,15(a1)    ;set mp_SigBit
  1170.         move.l    a1,-(sp)
  1171.         suba.l    a1,a1
  1172.         jsr    -$126(a6)    ;FindTask(0)
  1173.         move.l    (sp)+,a1
  1174.         move.l    d0,16(a1)    ;set mp_SigTask
  1175.         lea    reqlist(pc),a0
  1176.         move.l    a0,(a0)        ;NEWLIST begins...
  1177.         addq.l    #4,(a0)
  1178.         clr.l    4(a0)
  1179.         move.l    a0,8(a0)    ;NEWLIST ends...
  1180. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  1181.         addq.l    #1,d2
  1182.         lea    allocreq(pc),a1
  1183.         lea    audiodevname(pc),a0
  1184.         moveq    #0,d0
  1185.         moveq    #0,d1
  1186.         movea.l    4,a6
  1187.         jsr    -$1bc(a6)    ;OpenDevice()
  1188.         tst.b    d0
  1189.         bne.w    initerr
  1190.         st.b    audiodevopen
  1191. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ call 8-channel init routine
  1192.         bsr.w    _Init8chan
  1193.         moveq    #0,d0
  1194. initret:    movem.l    (sp)+,a4/a6/d2-d3
  1195.         rts
  1196. initerr:    move.l    d2,d0
  1197.         bra.s    initret
  1198.  
  1199. sigbitnum    dc.b    -1
  1200. audiodevopen    dc.b    0
  1201. allocmsk    dc.b    $0f,$00
  1202. chdmamask    dc.w    0
  1203. trksplit    dc.b    0,0,0,0
  1204.         even
  1205. allocport    dc.l    0,0    ;succ, pred
  1206.         dc.b    4,0    ;NT_MSGPORT
  1207.         dc.l    0    ;name
  1208.         dc.b    0,0    ;flags = PA_SIGNAL
  1209.         dc.l    0    ;task
  1210. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  1211.         dc.b    5,0
  1212. allocreq    dc.l    0,0
  1213.         dc.b    5,127    ;NT_MESSAGE, use maximum priority (127)
  1214.         dc.l    0,allocport    ;name, replyport
  1215.         dc.w    68        ;length
  1216.         dc.l    0        ;io_Device
  1217.         dc.l    0        ;io_Unit
  1218.         dc.w    0        ;io_Command
  1219.         dc.b    0,0        ;io_Flags, io_Error
  1220.         dc.w    0        ;ioa_AllocKey
  1221.         dc.l    allocmsk    ;ioa_Data
  1222.         dc.l    1        ;ioa_Length
  1223.         dc.w    0,0,0        ;ioa_Period, Volume, Cycles
  1224.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  1225. audiodevname    dc.b    'audio.device',0
  1226.  
  1227.         even
  1228. _periods:    dc.w 856,808,762,720,678,640,604,570,538,508,480,453
  1229.         dc.w 428,404,381,360,339,320,302,285,269,254,240,226
  1230.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1231.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1232.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1233.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  1234.  
  1235. _module8:    dc.l    0
  1236. holdvals:    ds.b    64
  1237.  
  1238.     IFND    __G2
  1239.         section "datachip",data,chip ;for A68k
  1240.     ENDC
  1241.     IFD    __G2
  1242.         section "datachip",data_c ;this is for Devpac 2
  1243.     ENDC
  1244.  
  1245.         XDEF    _modnum8
  1246. _audiobuff:    ds.w    200*8
  1247. _modnum8:    dc.w    0
  1248. _chipzero:    dc.w    0
  1249.  
  1250. ; the track-data structure definition:
  1251. trk_prevnote    equ    0    ;previous note number
  1252. trk_previnstr    equ    1    ;previous instrument number
  1253. trk_prevvol    equ    2    ;previous volume
  1254. trk_prevmidich    equ    3    ;previous MIDI channel
  1255. trk_cmd        equ    4    ;command (the 3rd number from right)
  1256. trk_cmdqual    equ    5    ;command qualifier (infobyte, databyte..)
  1257. trk_prevmidin    equ    6    ;previous MIDI note
  1258. trk_noteoffcnt    equ    7    ;note-off counter (hold)
  1259. trk_inithold    equ    8    ;default hold for this instrument
  1260. trk_initdecay    equ    9    ;default decay for....
  1261. trk_stransp    equ    10    ;instrument transpose
  1262. trk_pad0    equ    11
  1263. trk_previnstra    equ    12    ;address of the previous instrument data
  1264. trk_trackvol    equ    16
  1265.  
  1266. trk_prevper    equ    18    ;previous period
  1267. trk_audioaddr    equ    20    ;hardware audio channel base address
  1268. trk_sampleptr    equ    24    ;pointer to sample
  1269. trk_samplelen    equ    28    ;length (>> 1)
  1270. trk_porttrgper    equ    30    ;portamento (cmd 3) target period
  1271. trk_vibroffs    equ    32    ;vibrato table offset
  1272. trk_vibrspdsz    equ    33    ;vibrato speed/size (cmd 4 qualifier)
  1273. trk_synthptr    equ    34    ;pointer to synthetic/hybrid instrument
  1274. trk_arpgoffs    equ    38    ;SYNTH: current arpeggio offset
  1275. trk_arpsoffs    equ    40    ;SYNTH: arpeggio restart offset
  1276. trk_volxcnt    equ    42    ;SYNTH: volume execute counter
  1277. trk_wfxcnt    equ    43    ;SYNTH: waveform execute counter
  1278. trk_volcmd    equ    44    ;SYNTH: volume command pointer
  1279. trk_wfcmd    equ    46    ;SYNTH: waveform command pointer
  1280. trk_volwait    equ    48    ;SYNTH: counter for WAI (volume list)
  1281. trk_wfwait    equ    49    ;SYNTH: counter for WAI (waveform list)
  1282. trk_synthvibspd    equ    50    ;SYNTH: vibrato speed
  1283. trk_wfchgspd    equ    52    ;SYNTH: period change
  1284. trk_perchg    equ    54    ;SYNTH: curr. period change from trk_prevper
  1285. trk_envptr    equ    56    ;SYNTH: envelope waveform pointer
  1286. trk_synvibdep    equ    60    ;SYNTH: vibrato depth
  1287. trk_synvibwf    equ    62    ;SYNTH: vibrato waveform
  1288. trk_synviboffs    equ    66    ;SYNTH: vibrato pointer
  1289. trk_initvolxspd    equ    68    ;SYNTH: volume execute speed
  1290. trk_initwfxspd    equ    69    ;SYNTH: waveform execute speed
  1291. trk_volchgspd    equ    70    ;SYNTH: volume change
  1292. trk_prevnote2    equ    71    ;SYNTH: previous note
  1293. trk_synvol    equ    72    ;SYNTH: current volume
  1294. trk_synthtype    equ    73    ;>0 = synth, -1 = hybrid, 0 = no synth
  1295. trk_periodtbl    equ    74    ;pointer to period table
  1296. trk_prevportspd    equ    78    ;portamento (cmd 3) speed
  1297. trk_decay    equ    80    ;decay
  1298. trk_fadespd    equ    81    ;decay speed
  1299. trk_envrestart    equ    82    ;SYNTH: envelope waveform restart point
  1300. trk_envcount    equ    86    ;SYNTH: envelope counter
  1301. trk_split    equ    87    ;0 = this channel not splitted (OctaMED V2)
  1302.         end
  1303.