home *** CD-ROM | disk | FTP | other *** search
/ Da Capo / da_capo_vol1.bin / programs / amiga / edit / octamedv2 / programmers / modplayer / mod8player.a < prev    next >
Text File  |  1993-03-13  |  36KB  |  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