home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / amiga / midi / med.zoo / MED / Source / Player.zoo / player2.a < prev    next >
Encoding:
Text File  |  1990-04-09  |  18.3 KB  |  674 lines

  1. ;    MED - by Teijo Kinnunen, 1989, 1990
  2. ;    Player2.a, version 2.30
  3. ;    Use A68k (Fish #186) to assemble.
  4. custom    EQU    $dff000
  5. dmacon    EQU    $dff096
  6. aud0    EQU    $0A0
  7. aud1    EQU    $0B0
  8. aud2    EQU    $0C0
  9. aud3    EQU    $0D0
  10. ac_ptr    EQU    $00
  11. ac_len    EQU    $04
  12. ac_per    EQU    $06
  13. ac_vol    EQU    $08
  14.         xref    _song
  15.         xref    _samples
  16.         xref    _blocks
  17.         xref    _zeroptr
  18.  
  19.         section    "text",code
  20.         EVEN
  21.         dc.b    ' MEDPlayer is here!!!:' ;please, don't remove this
  22. waithwnum:    dc.l    500
  23. newaptr:    dc.l    0,0,0,0
  24. newalen:    dc.w    0,0,0,0
  25. audaddr:    dc.l    custom+aud0,custom+aud1,custom+aud2,custom+aud3
  26.  
  27. TrackOff:    ;d0 = channel #
  28.         moveq.l    #1,d1
  29.         lsl.w    d0,d1
  30.         move.w    d1,dmacon
  31. notamigatrk:    rts
  32. PlayNote:    ;d0 = trk #, d1 = note #, d2 = vol, d3 = instr #
  33.         movem.l    a2-a3/d3-d7,-(sp)    ;All right, let's start!!
  34.         move.w    d2,-(sp)
  35.         clr.l    d4
  36.         bset    d0,d4    ;d4 is mask for this channel
  37.         lea    _samples,a0        ;Is this instrument in mem?
  38.         lsl.w    #2,d3            ;d3 = instr.num << 2
  39.         tst.l    0(a0,d3.w)
  40.         beq.w    retsn2
  41.         add.b    _song+264,d1        ;add play transpose
  42.         bgt.s    notenot2low
  43.         add.b    #12,d1    ;note was too low, octave up
  44.         bra.s    endpttest
  45. notenot2low:    cmp.b    #72,d1
  46.         ble.s    endpttest
  47.         sub.b    #12,d1    ;note was too high, octave down
  48. endpttest:    move.w    d4,dmacon        ;stop this channel
  49.         lea    _song+268,a1
  50.         or.w    d4,dmaonmsk
  51.         subq.b    #1,d1
  52.         lsl.w    #1,d0
  53.         lsr.w    #1,d3
  54.         lea    newalen(pc),a2
  55.         clr.w    0(a2,d0.w)
  56.         move.w    d0,d6
  57.         lsl.w    #1,d6            ;d6 = channel num << 2
  58.         move.w    d3,d7
  59.         lsl.w    #1,d7            ;d7 = instr. num << 2
  60.         lea    audaddr,a1
  61.         movea.l    0(a1,d6.w),a1    ;base of this channel's regs
  62.         lea    newaptr(pc),a3        ;a3 = address of newaptr
  63.         lea    _samples,a2        ;get the address of...
  64.         move.l    0(a2,d7.w),d5        ;...this instrument
  65.         move.l    d5,a0
  66.         bsr.w    getinsdata
  67.         move.l    d0,ac_ptr(a1)        ;put start offs to ac_ptr
  68.         cmp.w    #2,d3
  69.         bls.s    norepeat
  70.         
  71.         add.l    d2,d0        ;d0 = starting address of repeat
  72.         move.l    d0,0(a3,d6.w)    ;remember!! (move to newaptr)
  73.         lsr.w    #1,d3        ;shift right
  74.         lsr.w    #1,d6
  75.         move.w    d3,16(a3,d6.w)    ;remember too (newalen)
  76.         lsr.w    #1,d2        ;shift
  77.         beq.s    begin0        ;rep. start < 2
  78.         move.w    d2,ac_len(a1)    ;move repeat to hardware
  79.         bra.s    retsn1
  80. begin0:        move.w    d3,ac_len(a1)
  81.         bra.s    retsn1
  82.                 
  83. norepeat:    move.l    zeroptr,0(a3,d6.w)    ;pointer of zero word
  84.         lea    newalen(pc),a3
  85.         lsr.w    #1,d6
  86.         move.w    #1,0(a3,d6.w)        ;length: 1 word
  87.         lsr.l    #1,d1            ;shift length right
  88.         move.w    d1,ac_len(a1)        ;and put to custom chip
  89.  
  90. retsn1:        move.w    d5,ac_per(a1)
  91.         lea    prevper(pc),a0
  92.         move.w    d5,0(a0,d6.w)
  93.         move.w    (sp),ac_vol(a1)        ;volume
  94. retsn2:        addq.l    #2,sp    ;forget volume
  95.         movem.l    (sp)+,a2-a3/d3-d7
  96.         rts
  97.  
  98. StartDMA:        ;This small routine turns on audio DMA
  99.         move.w    dmaonmsk,d0    ;dmaonmsk contains the mask of
  100.         beq.s    retsdma    ;the channels that must be turned on
  101.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  102.         move.l    waithwnum,d1
  103. waithw0:    dbf    d1,waithw0
  104.         move.w    d0,dmacon    ;do that!!!
  105.         move.l    waithwnum,d1
  106. waithw1:    dbf    d1,waithw1
  107.         lsr.b    #1,d0    ;finally, push new ptrs to audio hw regs
  108.         bcc.s    pushch1
  109.         move.l    newaptr(pc),custom+aud0+ac_ptr
  110.         move.w    newalen(pc),custom+aud0+ac_len
  111. pushch1:    lsr.b    #1,d0
  112.         bcc.s    pushch2
  113.         move.l    newaptr+4(pc),custom+aud1+ac_ptr
  114.         move.w    newalen+2(pc),custom+aud1+ac_len
  115. pushch2:    lsr.b    #1,d0
  116.         bcc.s    pushch3
  117.         move.l    newaptr+8(pc),custom+aud2+ac_ptr
  118.         move.w    newalen+4(pc),custom+aud2+ac_len
  119. pushch3:    lsr.b    #1,d0
  120.         bcc.s    retsdma
  121.         move.l    newaptr+12(pc),custom+aud3+ac_ptr
  122.         move.w    newalen+6(pc),custom+aud3+ac_len
  123. retsdma:    rts
  124.  
  125. dmaonmsk:    dc.w    0
  126. prevper:    dc.w    0,0,0,0
  127. prevnote:    dc.b    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  128. previnstr:    dc.b    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  129. prevvol:    dc.b    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  130. effect:        dc.b    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  131. effectqual:    dc.b    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  132. nextblock:    dc.b    0
  133. counter:    dc.b    5
  134. numtracks:    dc.b    0,0
  135. playstate:    dc.w    0
  136. playblock:    dc.w    0
  137. playline:    dc.w    0
  138. playblocknum    dc.w    0
  139.  
  140. IntHandler:
  141.         movem.l    d2-d7/a2-a4,-(sp)
  142.         tst.w    playstate    ;are we playing
  143.         bne.s    playing        ;yes, we are
  144.         and.b    #$fe,$bfee01    ;no...stop the timer
  145.         move.b    #$05,counter
  146.         movem.l    (sp)+,d2-d7/a2-a4    ;exit interrupt
  147.         rts
  148. playing:    clr.w    dmaonmsk
  149.         add.b    #1,counter
  150.         cmp.b    #6,counter    ;if counter = 6: new note and fx
  151.         bne.w    nonewnote    ;if counter is not 6: just do fx
  152.         clr.b    counter        ;new note!!!
  153.         clr.l    d7        ;number of track
  154.         lea    _blocks,a2    ;a2 = address of 1st block's address
  155.         move.w    playblock,d2
  156.         lsl.w    #2,d2        ;shift to longword index
  157.         movea.l    0(a2,d2.w),a2    ;get the pointer of the block
  158.         move.b    (a2),numtracks+1    ;save #áof tracks
  159.         addq.l    #4,a2        ;skip...
  160.         move.w    numtracks,d3
  161.         mulu    #3,d3
  162.         move.w    playline,d2
  163.         mulu    d2,d3
  164.         adda.l    d3,a2        ;a2 = address of this line
  165.         lea    prevnote(pc),a3
  166.         lea    _song,a4
  167. trloop0:    clr.w    d5
  168.         move.b    (a2)+,d5    ;get the number of this note
  169.         move.b    (a2)+,d6    ;and the 4 numbers containing fx
  170.         lsl.w    #8,d6
  171.         move.b    (a2)+,d6
  172.         lea    effectqual(pc),a1
  173.         move.b    d6,0(a1,d7.w)    ;save the fx numbers
  174.         clr.b    d4        ;d4 is a flag: if set, instr. is
  175.         btst    #7,d5        ;in range G-V. If clr, it's 1-F.
  176.         beq.s    nogtov        ;In the song, if bit #7 is set in
  177.         bclr    #7,d5        ;note number byte, it's G-V
  178.         st.b    d4        ;this instrument is in range G-V
  179. nogtov:        move.w    #$f000,d0
  180.         and.w    d6,d0        ;d0 now contains only the # of instr
  181.         bne.s    instnum        ;instrument number is not 0
  182.         tst.b    d4        ;maybe it's G (instr. #0, d4 set)
  183.         beq.s    noinstnum    ;no. It's 0!!!
  184. instnum:    lsr.w    #8,d0        ;shift it right to get number 0-F
  185.         lsr.b    #4,d0
  186.         tst.b    d4
  187.         beq.s    nogtov2
  188.         add.w    #16,d0        ;if G-V, add 16 to the number
  189. nogtov2:    lea    previnstr(pc),a1
  190.         move.b    d0,0(a1,d7.w) ;remember instr. number!
  191.         lea    prevvol(pc),a1
  192.         move.b    0(a4,d0.w),0(a1,d7.w)    ;vol of this instr to prevvol
  193. noinstnum:    move.w    d6,d0        ;effect again...
  194.         lsr.w    #8,d0
  195.         and.b    #$0f,d0        ;now check only the effect part
  196.         lea    effect(pc),a1
  197.         move.b    d0,0(a1,d7.w)    ;save the effect number
  198.         beq.s    noeffect    ;no effect
  199.         cmp.b    #$0f,d0        ;yes effect...is it Tempo???
  200.         bne.s    not0f        ;not Tempo
  201.         tst.b    d6        ;Tempo !!!
  202.         beq.s    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  203.         cmp.b    #$f0,d6        ;..is zero, go to next block
  204.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  205.         clr.l    d0        ;will happen!!!
  206.         move.b    d6,d0
  207.         bsr    SetTempo    ;change The Tempo
  208.         bra.s    noeffect
  209. fx0fspecial:    cmp.b    #$f2,d6    ; | rest - play | SpecialFX#2: no note..yet
  210.         bne.s    isfxfe    ;not SpecFX2
  211.         move.b    d5,(a3)    ;Yes!!! Save the note number
  212.         clr.w    d5    ; clear the number for awhile
  213.         bra.s    noeffect
  214. isfxfe:        cmp.b    #$fe,d6
  215.         bne.s    noeffect
  216.         clr.w    playstate
  217.         bra.s    noeffect
  218. fx0fchgblck:    st.b    nextblock    ;next block????...YES!!!! (F00)
  219.         bra.s    noeffect
  220. not0f:        cmp.b    #$0c,d0        ;new volume???
  221.         bne.s    noeffect    ;NO!!!!!!!!!!!!!!!!!!!!!!
  222.         move.b    d6,d0
  223.         lsr.b    #4,d0        ;Strange code begins now
  224.         mulu    #10,d0
  225.         move.b    d6,d1
  226.         and.b    #$0f,d1
  227.         add.b    d1,d0        ;strange code ends now: d0 is vol
  228.         cmp.b    #64,d0
  229.         bls.s    novolov64
  230.         moveq.l    #64,d0
  231. novolov64    lea    prevvol(pc),a1
  232.         move.b    d0,0(a1,d7.w)    ;and save it....
  233. noeffect:    tst.b    d5    ;Now we'll check if we have to play a note
  234.         beq.s    endtrkloop    ;no.
  235.         move.b    d5,(a3)
  236.         move.w    d7,d0
  237.         move.w    d5,d1
  238.         clr.w    d2
  239.         clr.w    d3
  240.         lea    previnstr(pc),a1
  241.         move.b    0(a1,d7.w),d3
  242.         lea    prevvol(pc),a1
  243.         move.b    0(a1,d7.w),d2    ;get volume
  244.         bsr    PlayNote    ;play it!!!!!!!!!!!
  245. endtrkloop:    addq.l    #1,a3        ;a3 = pointer to prev. note #
  246.         addq.l    #1,d7
  247.         cmp.w    numtracks,d7
  248.         blt.w    trloop0
  249.  
  250.         add.w    #1,playline    ;very important!!! advance line!!
  251.         cmp.w    #63,playline    ;important too!!! advance block??
  252.         bgt.s    chgblock    ;yes!!!
  253.         tst.b    nextblock    ;command F00 ??
  254.         beq.s    nochgblock    ;no, don't change block
  255. chgblock:    clr.w    playline    ;clear line number
  256.         cmp.w    #2,playstate    ;play block or play song
  257.         bne.s    nonewseq    ;play block only...
  258.         add.w    #1,playblocknum    ;advance sequence number
  259.         move.w    262(a4),d0    ;get the highest seq number
  260.         move.w    playblocknum,d1    ;and current seq number
  261.         cmp.w    d0,d1    ;is this the highest seq number
  262.         blt.s    nostartagain    ;no
  263.         clr.w    playblocknum    ;yes: play song again
  264.         clr.w    d1            ;...forever!!!
  265. nostartagain:    clr.w    d0
  266.         lea    162(a4),a1    ;offset of sequence table
  267.         move.b    0(a1,d1.w),d0    ;get number of the block
  268.         move.w    d0,playblock    ;and put it to block number var
  269.         move.w    160(a4),d1    ;get number of blocks
  270.         subq.w    #1,d1        ;# of blocks-1 = # of highest block
  271.         cmp.w    d1,d0        ;is this block number too big
  272.         blt.s    nonewseq    ;no
  273.         move.w    d1,playblock    ;yes..then play just the last block
  274. nonewseq:    clr.b    nextblock    ;clear this if F00 set it
  275. nochgblock:
  276. nonewnote:
  277. ;    *********************** This code produces the effects **
  278.         clr.l    d7    ;clear channel count
  279.         lea    prevper(pc),a3
  280.         lea    prevvol(pc),a4
  281. trloop1:    clr.w    d5
  282.         lea    effect,a1
  283.         clr.w    d4
  284.         move.b    0(a1,d7.w),d6    ;get the fx number
  285.         lea    effectqual,a1
  286.         move.b    0(a1,d7.w),d4    ;and the last 2 #'s
  287.         cmp.b    #1,d6        ;effect #1
  288.         bne.s    nofx01
  289. ;    **************************************** Effect 01 ******
  290.         cmp.w    #5,_song+266
  291.         bne.s    nost1
  292.         tst.b    counter
  293.         beq    newvals
  294. nost1:        sub.w    d4,(a3)    ;slide it up!!!
  295.         cmp.w    #113,(a3)    ;too high???
  296.         bge    newvals
  297.         move.w    #113,(a3)    ;yes, too high!!!
  298.         bra    newvals
  299. ;    *********************************************************
  300. nofx01:        cmp.b    #2,d6
  301.         bne.s    nofx02
  302. ;    **************************************** Effect 02 ******
  303.         cmp.w    #5,_song+266
  304.         bne.s    nost2
  305.         tst.b    counter
  306.         beq    newvals
  307. nost2:        add.w    d4,(a3)    ;slide it down!!!!!!!!!
  308.         cmp.w    #856,(a3)    ;too low??
  309.         ble    newvals
  310.         move.w    #856,(a3)    ;too low.
  311.         bra    newvals
  312. ;    *********************************************************
  313. nofx02:        tst.b    d6
  314.         bne.s    nofx00
  315. ;    **************************************** Effect 00 ******
  316.         tst.b    d4    ;both fxqualifiers are 0s: no arpeggio!!
  317.         beq.w    endl
  318.         lea    prevnote,a1
  319.         bsr.w    DoArpeggio
  320.         subq.b    #1,d4        ;-1 to make it 0 - 127
  321.         add.b    _song+264,d4    ;add play transpose
  322.         lsl.b    #1,d4        ;shift to make index for UWORD
  323.         lea    periods,a1
  324.         move.w    0(a1,d4.w),d5
  325.         bra.w    newvals
  326. ;    *********************************************************
  327. nofx00:        cmp.b    #$0d,d6
  328.         bne.s    nofx0d
  329. ;    **************************************** Effect 0D ******
  330.         move.b    d4,d1
  331.         move.b    (a4),d0    ;move previous vol to d0
  332.         and.b    #$f0,d1
  333.         bne.s    crescendo
  334.         sub.b    d4,d0    ;sub from prev. vol
  335.         bpl.s    novolund0
  336.         clr.b    d0    ;volumes under zero not accepted!!!
  337. novolund0:    move.b    d0,(a4)    ;put new vol back
  338.         bra    newvals
  339. crescendo:    lsr.b    #4,d1
  340.         add.b    d1,d0
  341.         cmp.b    #64,d0
  342.         ble.s    novolover64
  343.         moveq.l    #64,d0
  344. novolover64:    move.b    d0,(a4)
  345.         bra    newvals
  346. ;    *********************************************************
  347. nofx0d:        cmp.b    #3,d6
  348.         bne.s    nofx03
  349. ;    **************************************** Effect 03 ******
  350.         move.w    (a3),d5    ;this is very simple: get the old period
  351.         cmp.b    #3,counter    ;and..
  352.         bge.w    newvals        ;if counter < 3
  353.         sub.w    d4,d5    ;subtract effect qualifier
  354.         bra.w    newvals
  355. ;    *********************************************************
  356. nofx03:        cmp.b    #$0f,d6
  357.         bne.s    nofx0f
  358. ;    **************************************** Effect 0F ******
  359. fx0f:        cmp.b    #$ff,d4
  360.         bne.s    no0fff
  361.         move.w    d7,d0
  362.         bsr.w    TrackOff
  363.         bra.w    endl
  364. no0fff:        cmp.b    #$f1,d4
  365.         bne.s    no0ff1
  366.         cmp.b    #3,counter
  367.         bne.s    newvals
  368.         bra.s    playfxnote
  369. no0ff1:        cmp.b    #$f2,d4
  370.         bne.s    no0ff2
  371.         cmp.b    #3,counter
  372.         bne.s    newvals
  373.         bra.s    playfxnote
  374. no0ff2:        cmp.b    #$f3,d4
  375.         bne.s    endl
  376.         move.b    counter,d0
  377.         and.b    #2+4,d0        ;is 2 or 4
  378.         beq.s    newvals
  379. playfxnote:    move.w    d7,d0        ;track # to d0...
  380.         lea    prevnote(pc),a1
  381.         clr.w    d1
  382.         move.b    0(a1,d7.w),d1    ;get note # of previous note
  383.         clr.w    d2
  384.         move.b    (a4),d2        ;get previous volume
  385.         lea    previnstr(pc),a1
  386.         clr.w    d3
  387.         move.b    0(a1,d7.w),d3
  388.         bsr    PlayNote
  389.         bra.s    endl
  390. ;    *********************************************************
  391. nofx0f:        cmp.b    #$0e,d6
  392.         bne.s    nofx0e
  393. ;    **************************************** Effect 0E ******
  394. fx0e:        tst.b    d4
  395.         bne.s    filteroff
  396.         bclr    #1,$bfe001
  397.         bra.s    endl
  398. filteroff:    bset    #1,$bfe001
  399.         bra.s    endl
  400. ;    *********************************************************
  401. nofx0e:        cmp.b    #$0c,d6
  402.         bne.s    endl
  403. newvals:    tst.w    d5    ;now: do the effects!!!
  404.         bne.s    nonewper
  405.         move.w    (a3),d5    ;no new period specified: get the old
  406. nonewper:    move.w    d7,d4    ;channel number to d4
  407.         lsl.w    #2,d4    ;and shift it to make it a longword index
  408.         lea    audaddr,a1
  409.         movea.l    0(a1,d4.w),a1
  410.         move.w    d5,ac_per(a1)
  411.         clr.w    d5
  412.         move.b    (a4),d5
  413.         move.w    d5,ac_vol(a1)
  414. endl:        addq.l    #2,a3    ;inc pointer to previous period value
  415.         addq.l    #1,a4    ;and previous volume
  416.         addq.l    #1,d7    ;increment channel number
  417.         cmp.w    numtracks,d7    ;all channels done???
  418.         blt.w    trloop1    ;not yet!!!
  419.  
  420.         bsr    StartDMA    ;turn on DMA
  421. exitint:    movem.l    (sp)+,d2-d7/a2-a4
  422.         rts
  423. SetTempo:    tst.b    timeropen
  424.         beq.s    exitsettempo
  425.         cmp.b    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  426.         bhi.s    calctempo
  427.         lea    sttempo(pc),a1
  428.         lsl.w    #1,d0
  429.         move.w    0(a1,d0.w),d1
  430.         bra.s    pushtempo
  431. calctempo:    move.l    #470000,d1
  432.         divu    d0,d1
  433. pushtempo:    move.b    d1,$bfe401    ;and set the CIA timer
  434.         lsr.w    #8,d1
  435.         move.b    d1,$bfe501
  436. exitsettempo:    rts    ; vv-- These values are the SoundTracker tempos (approx.)
  437. sttempo:    dc.w    $0f00,2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  438.  
  439. DoArpeggio:    ; beginning note table in a1, note num returned in d4
  440.         move.b    0(a1,d7.w),d1    ;d1 = # of previous note played
  441.         move.b    counter,d0
  442.         tst.b    d0
  443.         beq.s    arpg03
  444.         cmp.b    #3,d0
  445.         bne.s    arpgn03
  446. arpg03:        and.b    #$0f,d4        ;counter = 0 or 3: get last number
  447.         add.b    d1,d4        ;add it to note number
  448.         rts
  449. arpgn03:    cmp.b    #1,d0
  450.         beq.s    arpg14
  451.         cmp.b    #4,d0
  452.         bne.s    arpgn14
  453. arpg14:        lsr.b    #4,d4    ;counter = 1 or 4: get the first number
  454.         add.b    d1,d4    ;add to prev. note
  455.         rts
  456. arpgn14:    move.b    d1,d4    ;2 or 5: the previous note
  457.         rts
  458.  
  459. getinsdata:    clr.l    d2
  460.         move.w    4(a0),d0    ;Soitin-struct in a0, instr#<<1: d3
  461.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  462.         move.l    a0,d0
  463.         lea    periods,a0
  464.         lsl.b    #1,d1
  465.         move.w    0(a0,d1.w),d5    ;put period to d5
  466.         move.l    d0,a0
  467.         addq.l    #6,d0        ;Skip structure
  468.         move.l    (a0),d1        ;length
  469.         lea    _song+32,a0
  470.         move.w    0(a0,d3.w),d2
  471.         move.w    64(a0,d3.w),d3
  472.         rts
  473. iff5or3oct:    movem.l    a1/d6-d7,-(sp)
  474.         clr.l    d7
  475.         move.w    d1,d7
  476.         divu    #12,d7    ;octave #
  477.         move.l    d7,d5
  478.         swap    d5    ;note number (0-11) in this oct to d5
  479.         move.l    (a0),d1
  480.         cmp.b    #2,d0
  481.         bne.s    no3oct
  482.         addq.l    #6,d7
  483.         divu    #7,d1    ;get length of the 1st octave
  484.         bra.s    no5oct
  485. no3oct:        divu    #31,d1    ;get length of the 1st octave (5 octaves)
  486. no5oct:        move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  487.         lea    _song+32,a1
  488.         move.w    0(a1,d3.w),d2
  489.         move.w    64(a1,d3.w),d3
  490.         clr.w    d6
  491.         move.b    shiftcnt(pc,d7.w),d6
  492.         lsl.w    d6,d2
  493.         lsl.w    d6,d3
  494.         lsl.w    d6,d1
  495.         move.b    mullencnt(pc,d7.w),d6
  496.         mulu    d6,d0        ;offset of this oct from 1st oct
  497.         add.l    a0,d0        ;add base address to offset
  498.         addq.l    #6,d0        ;skip structure
  499.         lea    periods,a1
  500.         add.b    octstart(pc,d7.w),d5
  501.         lsl.b    #1,d5
  502.         move.w    0(a1,d5.w),d5
  503.         movem.l    (sp)+,a1/d6-d7
  504.         rts
  505. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0
  506. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0
  507. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36
  508.  
  509. _AudioInit:    movem.l    a6/d2,-(sp)
  510.         clr.l    d2
  511.         movea.l    4,a6
  512. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ alloc signal bit
  513.         addq.l    #1,d2
  514.         st.l    d0    ; -1
  515.         jsr    -$14a(a6)    ;AllocSignal()
  516.         tst.b    d0
  517.         bmi.w    initerr
  518.         move.b    d0,sigbitnum
  519. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ prepare IORequest
  520.         suba.l    a1,a1
  521.         jsr    -$126(a6)    ;FindTask(0)
  522.         lea    allocport(pc),a1
  523.         move.b    sigbitnum,15(a1)    ;set mp_SigBit
  524.         move.l    d0,16(a1)    ;set mp_SigTask
  525.         lea    reqlist(pc),a0
  526.         move.l    a0,(a0)        ;NEWLIST begins...
  527.         addq.l    #4,(a0)
  528.         clr.l    4(a0)
  529.         move.l    a0,8(a0)    ;NEWLIST ends...
  530. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ open audio.device
  531.         addq.l    #1,d2
  532.         lea    allocreq(pc),a1
  533.         lea    audiodevname(pc),a0
  534.         clr.l    d0
  535.         clr.l    d1
  536.         movea.l    4,a6
  537.         jsr    -$1bc(a6)    ;OpenDevice()
  538.         tst.b    d0
  539.         bne.s    initerr
  540.         st.b    audiodevopen
  541. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ open ciaa.resource
  542.         addq.l    #1,d2
  543.         clr.l    d0
  544.         lea    ciaaname(pc),a1
  545.         jsr    -$1f2(a6)    ;OpenResource()
  546.         tst.l    d0
  547.         beq.s    initerr
  548.         move.l    d0,ciaaresource
  549. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ attach interrupt
  550.         addq.l    #1,d2
  551.         move.l    d0,a6
  552.         lea    timerinterrupt(pc),a1
  553.         clr.l    d0    ;Bit number 0: Timer A
  554.         jsr    -$6(a6)    ;AddICRVector
  555.         tst.l    d0
  556.         bne.s    initerr
  557.         and.b    #%10000000,$bfee01
  558.         move.l    #%10000001,d0
  559.         jsr    -$12(a6)    ;AbleICR()
  560.         st.b    timeropen
  561.         clr.w    playstate
  562.         clr.l    d0
  563. initret:    movem.l    (sp)+,a6/d2
  564.         rts
  565. initerr:    move.l    d2,d0
  566.         bra.s    initret
  567.  
  568. _AudioRem:    move.l    a6,-(sp)
  569.         tst.b    timeropen
  570.         beq.s    rem1
  571. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ remove interrupt
  572.         move.l    ciaaresource,a6
  573.         lea    timerinterrupt(pc),a1
  574.         clr.l    d0    ;Bit number 0: Timer A
  575.         jsr    -$c(a6)        ;RemICRVector
  576. ;There is no CloseResource(). I'm not sure if I should use CloseLibrary()??
  577. rem1:        movea.l    4,a6
  578.         tst.b    audiodevopen
  579.         beq.s    rem2
  580.         move.w    #$000f,dmacon    ;stop audio DMA
  581. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ close audio.device
  582.         lea    allocreq(pc),a1
  583.         jsr    -$1c2(a6)    ;CloseDevice()
  584. rem2:        clr.l    d0
  585.         move.b    sigbitnum,d0
  586.         bmi.s    rem3
  587. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ free signal bit
  588.         jsr    -$150(a6)    ;FreeSignal()
  589. rem3:        move.l    (sp)+,a6
  590.         rts
  591.  
  592.         xdef    _InitPlayer
  593.         xdef    _StartPlayer
  594.         xdef    _StopPlayer
  595.         xdef    _RemPlayer
  596.         xdef    SetTempo    ;for assembly programmers
  597.         xdef    _SetTempo    ;for C programmers
  598.  
  599. _InitPlayer:    bsr.w    _AudioInit
  600.         tst.b    d0
  601.         bne.s    iperror
  602.         moveq.l    #6,d0
  603.         bsr.w    SetTempo    ;default tempo
  604.         clr.l    d0    ;Init OK
  605. iperror:    rts
  606.  
  607. _RemPlayer:    bclr    #1,$bfe001    ;filter back on
  608.         tst.w    playstate
  609.         beq.s    nostop
  610.         bsr.s    _StopPlayer
  611. nostop:        bsr.w    _AudioRem
  612.         rts
  613.  
  614. _StartPlayer:    tst.b    timeropen
  615.         beq.s    exitsplr
  616.         clr.w    playblocknum     ;play from the beginning
  617.         move.b    _song+162,playblock+1 ;get the first block
  618.         clr.w    playline
  619.         move.w    #2,playstate
  620.         move.b    _song+265,d0
  621.         btst    #0,d0
  622.         bne.s    nofiloff
  623.         or.b    #2,$bfe001    ;set filter
  624. nofiloff:    or.b    #$01,$bfee01    ;start timer
  625. exitsplr:    rts
  626.  
  627. _StopPlayer:    clr.w    playstate    ;the interrupt will stop the timer
  628.         tst.b    audiodevopen
  629.         beq.s    exitstpplr
  630.         move.w    #$000f,dmacon    ;stop audio DMA
  631. exitstpplr:    rts
  632.  
  633. _SetTempo:    move.l    4(sp),d0
  634.         bra.w    SetTempo
  635.  
  636. ciaaresource:    dc.l    0
  637. zeroptr:    dc.l    _zeroptr ;_zeroptr is not really a pointer
  638. audiodevopen:    dc.b    0
  639. timeropen:    dc.b    0
  640. sigbitnum:    dc.b    -1
  641. timerinterrupt:    dc.w    0,0,0,0,0
  642.         dc.l    timerintname,0,IntHandler
  643. allocport:    dc.l    0,0    ;succ, pred
  644.         dc.b    4,0    ;NT_MSGPORT
  645.         dc.l    0    ;name
  646.         dc.b    0,0    ;flags = PA_SIGNAL
  647.         dc.l    0    ;task
  648. reqlist:    dc.l    0,0,0    ;list head, tail and tailpred
  649.         dc.b    5,0
  650. allocreq:    dc.l    0,0
  651.         dc.b    5,127    ;NT_MESSAGE, maximum priority (127)
  652.         dc.l    0,allocport    ;name, replyport
  653.         dc.w    68        ;length
  654.         dc.l    0    ;io_Device
  655.         dc.l    0    ;io_Unit
  656.         dc.w    0    ;io_Command
  657.         dc.b    0,0    ;io_Flags, io_Error
  658.         dc.w    0    ;ioa_AllocKey
  659.         dc.l    sttempo    ;ioa_Data
  660.         dc.l    1    ;ioa_Length
  661.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  662.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  663. periods:    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  664.         dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  665.         dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  666.         dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  667.         dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  668.         dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  669. ciaaname:    dc.b    'ciaa.resource',0
  670. timerintname:    dc.b    'Player: TimerInterrupt',0
  671. audiodevname:    dc.b    'audio.device',0
  672. medname:    dc.b    'MED',0 ;yeah, our name
  673.         end
  674.