home *** CD-ROM | disk | FTP | other *** search
/ Audio 4.94 - Over 11,000 Files / audio-11000.iso / amiga / midi / med210.lhw / in.adf / Source / med210src.lzh / med-player.a < prev    next >
Text File  |  1990-07-14  |  36KB  |  1,331 lines

  1. ;    MED V2.10 - ⌐ 1989, 1990 by Teijo Kinnunen
  2. ;    med-player.a    - konekielinen soittorutiini
  3. ;              the machine language player routine
  4. ac_ptr    EQU    $00
  5. ac_len    EQU    $04
  6. ac_per    EQU    $06
  7. ac_vol    EQU    $08
  8. T03SZ    EQU    24
  9. T415SZ    EQU    8
  10.         xdef    _GetSerial
  11.         xdef    _FreeSerial
  12.         xdef    _AddMIDIData
  13.         xdef    _AudioInit
  14.         xdef    _AudioRem
  15.         xdef    _ChannelOff
  16.         xdef    _SetTempo
  17.         xdef    _ResetMIDI
  18.         xref    _song
  19.         xref    _PiirraPylvas
  20.         xref    _sample
  21.         xref    _trackon
  22.         xref    _zeroptr
  23.         xref    _periodit
  24.         xref    _specialupd
  25.         xref    _counter
  26.         xref    DrawEqualizer
  27.         xref    ClrChanDisp
  28.         xref    SetDisp1
  29.         xref    SetDisp2
  30.         xref    SetDisp3
  31.  
  32.         section    "text",code
  33.         EVEN
  34.  
  35. _ChannelOff:    ;d0 = channel #
  36.         lea    trackdataptrs(pc),a1
  37.         lsl.b    #2,d0
  38.         adda.w    d0,a1
  39.         lsr.b    #2,d0
  40.         movea.l    (a1),a1
  41.         move.b    6(a1),d1    ;first: is it MIDI??
  42.         beq.s    notcomidi    ;not a midi note
  43.         lea    noteondata(pc),a0
  44.         clr.l    (a0)        ; new midi msg
  45.         move.b    d1,1(a0)
  46.         move.b    3(a1),(a0)    ;prev midi channel
  47.         or.b    #$80,(a0)        ;note off
  48.         moveq.l    #3,d0
  49.         bra.w    _AddMIDIData
  50. notcomidi:    cmp.b    #4,d0
  51.         bge.s    notamigatrk
  52.         moveq.l    #1,d1
  53.         lsl.w    d0,d1
  54.         move.w    d1,$dff096
  55.         jsr    ClrChanDisp(pc)
  56. notamigatrk:    rts
  57. ; track # = d7, note vol = d0, song = a4
  58. GetRelVol:    clr.w    d1
  59.         clr.w    d2
  60.         move.b    3330(a4),d1        ;master volume
  61.         lea    3314(a4),a0
  62.         move.b    0(a0,d7.w),d2        :track volume
  63.         mulu    d2,d0
  64.         mulu    d1,d0    ;d0 = master v. * track v. * volume
  65.         lsr.l    #4,d0
  66.         lsr.w    #8,d0
  67.         rts
  68. _SoitaNuotti:    ;d0 = trk #, d1 = note #, d2 = vol, d3 = instr # a3 = addr of instr
  69.         movem.l    d3-d7,-(sp)    ;All right, let's start!!
  70.         move.w    d2,-(sp)
  71.         clr.l    d4
  72.         bset    d0,d4    ;d4 is mask for this channel
  73.         lea    _sample,a0        ;Is this instrument in mem?
  74.         move.w    d3,d7
  75.         lsl.w    #2,d7            ;d7 = instr.num << 2
  76.         tst.l    0(a0,d7.w)
  77.         bne.s    inmem
  78.         tst.b    44(a3)            ;is MIDI channel set
  79.         beq.w    retsn2            ; NO!!!
  80. inmem:        lea    _trackon,a0        ;Is this track on??
  81.         lsl.w    #1,d0            ;d0 = track num << 1
  82.         tst.w    0(a0,d0.w)
  83.         beq.w    retsn2            ; NO!!!!!!
  84.         lsr.w    #1,d0
  85.         add.b    3290(a4),d1    ;add play transpose
  86.         add.b    47(a3),d1    ;and instr. transpose
  87.         jsr    DrawEqualizer(pc)
  88.         cmp.b    #4,d0
  89.         bge.s    nodmaoff    ;track #á>= 4: not an Amiga channel
  90.         jsr    ClrChanDisp(pc)
  91.         move.w    d4,$dff096        ;stop this channel (dmacon)
  92. nodmaoff:    move.b    6(a5),d6        ;get prev. midi note
  93.         beq.s    noprevmidi
  94.         clr.b    6(a5)
  95.         lea    noteondata(pc),a0
  96.         move.b    d6,1(a0)
  97.         move.b    3(a5),(a0)    ;prev midi channel
  98.         or.b    #$90,(a0)        ;note off
  99.         clr.b    2(a0)        ;clear volume
  100.         movem.l    d0-d1,-(sp)
  101.         moveq.l    #3,d0
  102.         bsr.w    _AddMIDIData
  103.         movem.l    (sp)+,d0-d1
  104. noprevmidi:    tst.b    44(a3)
  105.         bne.w    handleMIDInote
  106. tlwtst0:        tst.b    d1
  107.         bgt.s    notenot2low
  108.         add.b    #12,d1    ;note was too low, octave up
  109.         bra.s    tlwtst0
  110. notenot2low:    cmp.b    #63,d1
  111.         ble.s    endpttest
  112.         sub.b    #12,d1    ;note was too high, octave down
  113. endpttest:    cmp.b    #4,d0        ;test track # again
  114.         bge.w    retsn2        ;no Amiga instruments in tracks > 3
  115.         or.w    d4,dmaonmsk
  116.         subq.b    #1,d1
  117.         movea.l    10(a5),a1    ;base of this channel's regs
  118.         lea    _sample,a0        ;get the address of...
  119.         movea.l    0(a0,d7.w),a0        ;...this instrument
  120.         lsl.w    #1,d3
  121.         move.w    d0,d4    ;d4 = track number
  122.         bsr.w    getinsdata
  123.         move.l    d0,ac_ptr(a1)        ;put it in ac_ptr
  124.         move.w    (sp),d6    ;volume
  125.         jsr    SetDisp1(pc)
  126.         cmp.w    #1,d3
  127.         bhi.s    repeat
  128.         
  129.         move.l    _zeroptr,14(a5)        ;pointer of zero word
  130.         move.w    #1,18(a5)        ;length: 1 word
  131.         lsr.l    #1,d1            ;shift length right
  132.         move.w    d1,ac_len(a1)        ;and put to custom chip
  133.         bra.s    retsn1
  134.  
  135. repeat:        tst.w    d2
  136.         beq.s    begin0        ;rep. start < 2
  137.         move.w    d2,ac_len(a1)    ;move repeat to hardware
  138.         bra.s    beginn0
  139. begin0:        move.w    d3,ac_len(a1)
  140. beginn0:        lsl.l    #1,d2        ;shift
  141.         add.l    d2,d0        ;d0 = starting address of repeat
  142.         move.l    d0,14(a5)    ;remember rep. start
  143.         move.w    d3,18(a5)    ;remember rep. length
  144.                 
  145. retsn1:        move.w    d5,ac_per(a1)    ;getinsdata puts period to d5
  146.         jsr    SetDisp2(pc)
  147.         move.w    d5,8(a5)
  148.         move.w    (sp),ac_vol(a1)        ;volume
  149.         lsr.w    #2,d7        ;d7 is now instr. number again
  150. drawcol:        move.w    d7,d0        ;to d0
  151.         cmp.b    #31,d0
  152.         bge.s    nodraw
  153.         clr.l    d1
  154.         move.w    (sp),d1        ;volume (height) to d1
  155.         lsr.b    #1,d1        ;to range 0 - 32
  156.         and.b    #$fe,d1        ;must be even
  157.         beq.s    nodraw        ;volume = 1, don't draw
  158.         jsr    _PiirraPylvas(pc)    ;draw it
  159. nodraw:        move.b    3291(a4),d0        ;flags
  160.         btst    #1,d0            ;jumping ??
  161.         beq.s    retsn2            ;no...
  162.         btst    #2,d0            ;with instruments
  163.         bne.s    retsn2            ;no......
  164.         move.l    3294(a4),d0        ;yes!!!, get instr. mask
  165.         lsr.l    d7,d0            ;set this instr. to bit #0
  166.         btst    #0,d0            ;and test it
  167.         beq.s    retsn2            ;no jump with this instr
  168.         move.b    #1,animcnt        ;init animation counter
  169. retsn2:        addq.l    #2,sp    ;forget volume
  170.         movem.l    (sp)+,d3-d7
  171.         rts
  172.  
  173. handleMIDInote:
  174.         lea    noteondata(pc),a0
  175.         add.b    #23,d1        ;2 octaves higher and -1
  176.         bpl.s    mnot2low    ;note number not too low
  177.         add.b    #12,d1        ;it was too low, 1 octave up
  178.         bra.s    endmtst
  179. mnot2low:    tst.b    d1        ;is it too high then??
  180.         bpl.s    endmtst        ;no, not greater than 127
  181.         sub.b    #12,d1        ;1 octave down, if yes
  182. endmtst:        move.b    d1,1(a0)    ;MIDI msg note #
  183.         move.b    d1,6(a5)    ;save this note number
  184.         move.b    d2,d4        ;temporary save the volume
  185.         subq.b    #1,d2        ;if 64 => 63
  186.         bpl.s    nooops
  187.         clr.b    d2        ;oops, too low!!
  188. nooops:        lsl.b    #1,d2        ;volume 0 - 63 => 0 - 127
  189.         bclr    #7,d2        ;be sure that bit 7 is clear
  190.         move.b    d2,2(a0)    ;MIDI msg volume
  191.         clr.w    d1
  192.         move.b    44(a3),d1    ;get midi chan of this instrument
  193.         subq.b    #1,d1        ;from 1-16 to 0-15
  194.         move.b    d1,3(a5)    ;save to prev midi channel
  195.         move.b    #$90,(a0)    ;MIDI: Note on
  196.         or.b    d1,(a0)        ;MIDI msg Note on & channel
  197.         move.b    45(a3),d2    ;get preset #
  198.         beq.s    nochgpres    ;zero = no preset
  199.         lea    prevmidicpres(pc),a1
  200.         cmp.b    0(a1,d1.w),d2    ;is this previous preset ??
  201.         beq.s    nochgpres    ;yes...no need to change
  202.         move.b    d2,0(a1,d1.w)    ;save preset to prevmidicpres
  203.         subq.b    #1,d2        ;sub 1 to get 0 - 127
  204.         lea    preschgdata(pc),a0
  205.         move.b    #$c0,(a0)    ;command: $C
  206.         or.b    d1,(a0)        ;"or" midi channel
  207.         move.b    d2,1(a0)    ;push the number to second byte
  208.         moveq.l    #5,d0        ;Noteondata follows preschgdata
  209.         bra.s    preschanged    ;struct, so this is a bit faster
  210. nochgpres:    moveq.l    #3,d0
  211. preschanged:    bsr.w    _AddMIDIData
  212.         move.w    d3,d7
  213.         bra.w    drawcol
  214.  
  215. waitamoment:    move.l    d0,-(sp)
  216.         moveq.l    #$79,d0
  217. wl0:        move.b    $dff007,d1
  218. wl1:        cmp.b    $dff007,d1
  219.         beq.s    wl1
  220.         dbf    d0,wl0
  221.         move.l    (sp)+,d0
  222.         rts
  223. pushnewvals:    movea.l    (a1)+,a5
  224.         lsr.b    #1,d0
  225.         bcc.s    rpnewv
  226.         movea.l    10(a5),a0
  227.         move.l    14(a5),ac_ptr(a0)
  228.         move.w    18(a5),ac_len(a0)
  229. rpnewv:        rts
  230. _StartDMA:        ;This small routine turns on audio DMA
  231.         move.w    dmaonmsk(pc),d0    ;dmaonmsk contains the mask of
  232.         beq.s    rpnewv    ;the channels that must be turned on
  233.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  234.         bsr.s    waitamoment
  235.         move.w    d0,$dff096    ;do that!!!
  236.         bsr.s    waitamoment
  237.         lea    trackdataptrs(pc),a1
  238.         bsr.s    pushnewvals
  239.         bsr.s    pushnewvals
  240.         bsr.s    pushnewvals
  241.         bra.s    pushnewvals
  242.  
  243.         xref    _mouse1
  244.         xref    _mouse2
  245.         xref    _mouse3
  246.         xref    _mouse4
  247.         xref    _mouse5
  248. frame:    dc.l    0,_mouse2,_mouse3,_mouse4,_mouse5,_mouse5,_mouse4,_mouse3
  249.     dc.l    _mouse2,_mouse1,0
  250. dmaonmsk:    dc.w    0
  251. animcnt:    dc.b    0,0
  252. prevmidicpres:    dc.l    0,0,0,0 ; 16 bytes
  253. prevmidipbend:    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  254.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  255. ;    Track-data structure for each track
  256. ;    0(ax) previous note    1(ax) previous instrument
  257. ;    2(ax) previous volume    3(ax) previous midi channel
  258. ;    4(ax) command        5(ax) command qualifier (data byte)
  259. ;    6(ax) prev MIDI note    7(ax) prev. portamento speed (on MIDI
  260. ;---and for Amiga tracks also..       tracks it's only pad byte)
  261. ;    8(ax) previous period(w) 10(ax) base address of audio registers(l)
  262. ;    14(ax) new sample ptr(l) 18(ax) new sample length(w)
  263. ;    20(ax) portamento target period(w)
  264. ;    22(ax) curr vibrato offs 23(ax) curr vibrato speed/size
  265. t03d:        dc.w    0,0,0,0,0
  266.         dc.l    $dff0a0,0
  267.         dc.w    0,0,0,0,0,0,0,0
  268.         dc.l    $dff0b0,0
  269.         dc.w    0,0,0,0,0,0,0,0
  270.         dc.l    $dff0c0,0
  271.         dc.w    0,0,0,0,0,0,0,0
  272.         dc.l    $dff0d0,0
  273.         dc.w    0,0,0        ;24 bytes * 4 tracks = 92 bytes
  274. t415d:        ds.b    8*12    ;8 bytes * 12 tracks = 96 bytes
  275. trackdataptrs:    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  276.         dc.l    t415d,t415d+T415SZ,t415d+2*T415SZ,t415d+3*T415SZ
  277.         dc.l    t415d+4*T415SZ,t415d+5*T415SZ,t415d+6*T415SZ
  278.         dc.l    t415d+7*T415SZ,t415d+8*T415SZ,t415d+9*T415SZ
  279.         dc.l    t415d+10*T415SZ,t415d+11*T415SZ
  280. nextblock:    dc.b    0
  281. animpause:    dc.b    1
  282. numtracks:    dc.b    0,0
  283.         xref    _pstate
  284.         xref    _pblock
  285.         xref    _lohko
  286.         xref    _pline
  287.         xref    _actplayline
  288.         xref    _pseqnum
  289.         xref    _blocks
  290.         xref    _updscrflag
  291.         xref    _maintsk
  292.         xref    _updscrmsk
  293.         xref    _tempo
  294.         xref    _sprptr
  295.         xref    _hyppymsk
  296.         xref    _keybnote
  297. _IntHandler:
  298.         movem.l    d2-d7/a2-a5,-(sp)
  299.         tst.b    _keybnote ;Do we have to play note from keyboard
  300.         beq.s    nokbnote    ;no...just normal playing
  301.         lea    _keybnote,a1    ;get the address of the structure
  302.         lea    _song,a4    ;and the song
  303.         lea    4(a4),a3    ;ptr to sample structures
  304.         clr.w    dmaonmsk
  305.         moveq.l    #0,d0
  306.         moveq.l    #0,d1
  307.         moveq.l    #0,d2
  308.         moveq.l    #0,d3
  309.         clr.w    d7
  310.         move.b    3(a1),d7    ;get all these values from
  311.         move.b    d7,d0
  312.         lsl.b    #2,d0
  313.         movea.l    trackdataptrs(pc,d0.w),a5
  314.         move.b    2(a1),d3
  315.         move.w    d3,d4
  316.         mulu    #48,d4
  317.         adda.w    d4,a3
  318.         move.b    46(a3),d0
  319.         bsr.w    GetRelVol
  320.         move.b    d0,d2
  321.         move.b    d7,d0
  322.         move.b    1(a1),d1    ;the command structure
  323.         clr.b    (a1)        ;clear the play note flag
  324.         bsr    _SoitaNuotti    ;and play the note finally
  325.         bsr    _StartDMA
  326.         bra.s    notplaying    ;exit
  327. nokbnote:    tst.w    _pstate    ;are we playing
  328.         bne.s    playing        ;yes, we are
  329.         movea.l    craddr(pc),a0
  330.         bclr    #0,(a0)        ;no...stop the timer
  331.         move.b    #$05,_counter
  332.         clr.b    animcnt
  333.         move.l    frame+36(pc),_sprptr
  334.         bra.w    sigjump
  335. notplaying:    movem.l    (sp)+,d2-d7/a2-a5    ;exit interrupt
  336.         rts
  337. playing:        clr.w    dmaonmsk
  338.         lea    _song,a4
  339.         add.b    #1,_counter
  340.         cmp.b    #6,_counter    ;if counter = 6: new note and fx
  341.         bne.w    nonewnote    ;if counter is not 6: just do fx
  342. ; --- new note!! first get address of current block
  343.         lea    _lohko,a0    ;a2 = address of 1st block's address
  344.         move.w    _pblock,d2
  345.         lsl.w    #2,d2        ;shift to longword index
  346.         movea.l    0(a0,d2.w),a2    ;get the pointer of the block
  347.         clr.w    d0
  348.         move.b    1(a2),d0    ;get number of lines in this block
  349. ; and advance song pointers
  350.         lea    _actplayline,a3
  351.         addq.w    #1,(a3)        ;very important!!! advance line!!
  352.         cmp.w    (a3),d0         ;important too!!! advance block??
  353.         blt.s    chgblock    ;yes!!!
  354.         tst.b    nextblock    ;command F00 ??
  355.         beq.s    nochgblock    ;no, don't change block
  356. chgblock:    clr.w    (a3)        ;clear line number
  357.         cmp.w    #2,_pstate    ;play block or play song
  358.         bne.s    nonewseq    ;play block only...
  359.         cmp.b    #$01,nextblock
  360.         beq.s    posjump
  361.         addq.w    #1,_pseqnum    ;advance sequence number
  362. posjump:        move.w    3030(a4),d0    ;get the highest seq number
  363.         move.w    _pseqnum,d1    ;and current seq number
  364.         cmp.w    d0,d1    ;is this the highest seq number
  365.         blt.s    nostartagain    ;no
  366.         clr.w    _pseqnum    ;yes: play song again
  367.         clr.w    d1            ;...forever!!!
  368. nostartagain:    clr.w    d0
  369.         lea    3032(a4),a1    ;offset of sequence table
  370.         move.b    0(a1,d1.w),d0    ;get number of the block
  371.         move.w    d0,_pblock    ;and put it to block number var
  372.         clr.w    d1
  373.         move.b    _blocks,d1    ;get number of blocks
  374.         subq.w    #1,d1        ;# of blocks-1 = # of highest block
  375.         cmp.w    d1,d0        ;is this block number too big
  376.         blt.s    nolstblk    ;no
  377.         move.w    d1,_pblock    ;yes..then play just the last block
  378.         move.w    d1,d0
  379. nolstblk:    lsl.w    #2,d0
  380.         movea.l    0(a0,d0.w),a2    ;get address of new block
  381. nonewseq:    clr.b    nextblock    ;clear this if F00 set it
  382. nochgblock:    move.w    (a3),_pline
  383.         tst.w    _updscrflag    ;screen updating on??
  384.         beq.s    noscrupd    ;no
  385.         movea.l    _maintsk,a1    ;ask the main task to update screen
  386.         move.l    _updscrmsk,d0
  387.         jsr    -$144(a6)    ;Signal()
  388. ; --- now start to play it
  389. noscrupd:    clr.b    _counter
  390.         clr.l    d7        ;number of track
  391.         move.b    (a2),numtracks+1    ;save #áof tracks
  392.         lea    36(a2),a2    ;skip block header...
  393.         move.w    numtracks(pc),d3
  394.         mulu    #3,d3
  395.         move.w    _pline,d2
  396.         mulu    d2,d3
  397.         adda.l    d3,a2        ;a2 = address of this line
  398.         pea    trackdataptrs(pc)
  399. trloop0:        clr.w    d5
  400.         move.l    (sp),a1
  401.         movea.l    (a1)+,a5    ;get address of this track's struct
  402.         move.l    a1,(sp)
  403. ; ---------------- get the note numbers
  404.         move.b    (a2)+,d5    ;get the number of this note
  405.         move.b    (a2)+,d6    ;and the 4 numbers containing fx
  406.         lsl.w    #8,d6
  407.         move.b    (a2)+,d6
  408.         move.b    d6,5(a5)    ;save the fx numbers
  409. ; ---------------- clear some instrument # flags
  410.         clr.b    d4        ;d4 is a flag: if set, instr. is
  411.         clr.b    d3        ;in range G-V. If clr, it's 1-F.
  412. ; ---------------- and set them, if needed
  413.         bclr    #7,d5        ;d3 is also a flag. If it's set,
  414.         sne.b    d4        ;the instr. is in range 10 - 1V
  415.         bclr    #6,d5
  416.         sne.b    d3
  417. ; ---------------- check if there's an instrument number
  418.         move.w    #$f000,d0
  419.         and.w    d6,d0        ;d0 now contains only the # of instr
  420.         bne.s    instnum        ;instrument number is not 0
  421.         tst.b    d4        ;maybe it's G (instr. #0, d4 set)
  422.         bne.s    instnum        ;yes, it really was G!!
  423.         tst.b    d3
  424.         beq.s    noinstnum    ;it wasn't 10 - 1V either..
  425. ; ---------------- if there was, GET IT!!
  426. instnum:        lsr.w    #8,d0        ;shift it right to get number 0-F
  427.         lsr.b    #4,d0
  428.         tst.b    d4
  429.         beq.s    nogtov2
  430.         add.w    #16,d0        ;if G-V, add 16 to the number
  431. nogtov2:        tst.b    d3
  432.         beq.s    no10to1v
  433.         add.w    #32,d0
  434. ; ---------------- finally, save the number
  435. no10to1v:    subq.b    #1,d0
  436.         move.b    d0,1(a5) ;remember instr. number!
  437. ; ---------------- get the pointer of data's of this sample in Song-struct
  438.         lea    4(a4),a3    ;skip "MED\x04"
  439.         mulu    #48,d0        ;get address of this sample's data
  440.         adda.w    d0,a3        ;a3 contains now address of it
  441.         moveq.l    #0,d0
  442. ; ---------------- get volume and make it relative (0 - 100 %)
  443.         move.b    46(a3),d0
  444.         bsr.w    GetRelVol
  445.         move.b    d0,2(a5)    ;vol of this instr to prevvol
  446. ; ---------------- check the commands
  447. noinstnum:    move.w    d6,d0        ;effect again...
  448.         lsr.w    #8,d0
  449.         and.b    #$0f,d0        ;now check only the effect part
  450.         move.b    d0,4(a5)    ;save the effect number
  451.         beq.w    noeffect    ;no effect
  452. ; ---------------- there was a command (effect), but what??
  453.         cmp.b    #$0f,d0        ;yes effect...is it Tempo???
  454.         bne.s    not0f        ;not Tempo
  455. ; ---------------- it was tempo (F)
  456.         tst.b    d6        ;Tempo !!!
  457.         beq.s    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  458.         cmp.b    #$f0,d6        ;..is zero, go to next block
  459.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  460. ; ---------------- just an ordinary "change tempo"-request
  461.         clr.l    d0        ;will happen!!!
  462.         move.b    d6,d0
  463.         bsr    _SetTempo    ;change The Tempo
  464.         bra.w    noeffect
  465. ; ---------------- no, it was FFx, something special will happen!!
  466. fx0fspecial:    cmp.b    #$f2,d6    ; | rest - play | SpecialFX#2: no note..yet
  467.         bne.s    isfxfe    ;not SpecFX2
  468. ; ---------------- it was FF2, nothing to do now
  469.         move.b    d5,(a5)    ;Yes!!! Save the note number
  470.         clr.w    d5    ; clear the number for awhile
  471.         bra.w    noeffect
  472. isfxfe:        cmp.b    #$fe,d6
  473.         bne.s    notcmdfe
  474. ; ---------------- it was FFE, stop playing
  475.         clr.w    _pstate
  476.         or.b    #2,_specialupd
  477.         bra.w    noeffect
  478. notcmdfe:    cmp.b    #$fd,d6 ;change period
  479.         bne.w    noeffect
  480. ; ---------------- FFD, change the period, don't replay the note
  481.         cmp.b    #$04,d7 ;no tracks 4 - 15, thank you!!
  482.         bge.w    noeffect
  483.         lea    _periodit,a0
  484.         tst.b    d5
  485.         beq.w    noeffect ;hey, no note here!!
  486.         subq.b    #1,d5    ;sub 1 to make "real" note number
  487.         lsl.b    #1,d5
  488.         move.w    0(a0,d5.w),d0 ;get the period
  489.         movea.l    10(a5),a0
  490.         move.w    d0,ac_per(a0) ;push the period
  491.         clr.b    d5 ;and clear it so that it won't be replayed
  492.         bra.w    noeffect      ;done!!
  493. ; ---------------- F00, called Pattern Break in ST
  494. fx0fchgblck:    st.b    nextblock    ;next block????...YES!!!! (F00)
  495.         bra.w    noeffect
  496. ; ---------------- was not Fxx, then it's something else!!
  497. not0f:        cmp.b    #$0c,d0        ;new volume???
  498.         bne.s    not0c        ;NO!!!!!!!!!!!!!!!!!!!!!!
  499. ; ---------------- change volume
  500.         move.b    d6,d0
  501.         btst    #4,3291(a4)    ;look at flags
  502.         bne.s    volhex
  503.         lsr.b    #4,d0        ;get number from left
  504.         mulu    #10,d0        ;number of tens
  505.         move.b    d6,d1        ;get again
  506.         and.b    #$0f,d1        ;this time don't get tens
  507.         add.b    d1,d0        ;add them
  508. volhex:        cmp.b    #64,d0
  509.         bls.s    novolov64
  510.         moveq.l    #64,d0
  511. novolov64:    bsr.w    GetRelVol
  512.         move.b    d0,2(a5)    ;and save it....
  513.         bra.s    noeffect
  514. not0c:        cmp.b    #$0b,d0
  515.         bne.s    not0b
  516. ; ---------------- cmd Bxx, "position jump", like Goto, yΣk!!
  517.         move.w    d6,d0
  518.         and.w    #$00ff,d0
  519.         cmp.w    3030(a4),d0    ;test the song length
  520.         bhi.s    noeffect
  521.         move.w    d0,_pseqnum
  522.         move.b    #$01,nextblock
  523.         bra.s    noeffect
  524. ; ---------------- try portamento (3)
  525. not0b:        cmp.b    #$03,d0
  526.         bne.s    noeffect
  527.         subq.b    #1,d5
  528.         bmi.s    endtrkloop    ;it was 0, do nothing
  529.         cmp.b    #4,d7
  530.         bge.s    endtrkloop    ;hey, what are you trying to do??
  531.         lea    _periodit,a0
  532.         add.b    3290(a4),d5    ;play transpose
  533.         clr.w    d0
  534.         move.b    1(a5),d0
  535.         mulu    #48,d0
  536.         add.b    51(a4,d0.w),d5    ;and instrument transpose
  537.         bmi.s    endtrkloop    ;again.. too low
  538.         lsl.w    #1,d5
  539.         move.w    0(a0,d5.w),20(a5) ;period of this note is the target
  540.         move.b    d6,7(a5)    ;remember size
  541.         clr.b    d5    ;don't play this one
  542. ; ---------------- everything is checked now: play or not to play??
  543. noeffect:    tst.b    d5    ;Now we'll check if we have to play a note
  544.         beq.s    endtrkloop    ;no.
  545. ; ---------------- we decided to play
  546.         move.b    d5,(a5)
  547.         move.w    d7,d0
  548.         move.w    d5,d1
  549.         clr.w    d3
  550.         move.b    1(a5),d3
  551.         move.w    d3,d2
  552.         lea    4(a4),a3    ;skip "MED\x04"
  553.         mulu    #48,d3        ;get address of this sample's data
  554.         adda.w    d3,a3        ;a3 contains now address of it
  555.         move.w    d2,d3
  556.         clr.w    d2
  557.         move.b    2(a5),d2    ;get volume
  558.         bsr    _SoitaNuotti    ;play it!!!!!!!!!!!
  559. ; ---------------- end of loop: handle next track, or quit
  560. endtrkloop:    addq.b    #1,d7
  561.         cmp.w    numtracks(pc),d7
  562.         blt.w    trloop0
  563.         addq.l    #4,sp        ;trackdataptrs
  564. nonewnote:
  565. ;    *********************** This code produces the effects **
  566.         clr.l    d7    ;clear track count
  567.         lea    trackdataptrs(pc),a2
  568. trloop1:        movea.l    (a2)+,a5
  569.         clr.w    d5
  570.         clr.w    d4
  571.         move.b    4(a5),d6    ;get the fx number
  572.         move.b    5(a5),d4    ;and the last 2 #'s
  573.         tst.b    6(a5)        ;first: is it MIDI??
  574.         bne.w    midifx
  575.         cmp.b    #4,d7
  576.         bge.w    endl    ;no non-MIDI effects in tracks 4 - 15
  577.         cmp.b    #1,d6        ;effect #1
  578.         bne.s    nofx01
  579. ;    **************************************** Effect 01 ******
  580.         btst    #5,3291(a4)
  581.         beq.s    nost1
  582.         move.b    3293(a4),d0
  583.         cmp.b    _counter,d0
  584.         ble.w    endl
  585. nost1:        sub.w    d4,8(a5)    ;slide it up!!!
  586.         move.w    8(a5),d5
  587.         cmp.w    #113,d5        ;too high???
  588.         bge    newvals
  589.         move.w    #113,d5        ;yes, too high!!!
  590.         move.w    d5,8(a5)
  591.         bra    newvals
  592. ;    *********************************************************
  593. nofx01:        cmp.b    #2,d6
  594.         bne.s    nofx02
  595. ;    **************************************** Effect 02 ******
  596.         btst    #5,3291(a4)
  597.         beq.s    nost2
  598.         move.b    3293(a4),d0
  599.         cmp.b    _counter,d0
  600.         ble.w    endl
  601. nost2:        add.w    d4,8(a5)    ;slide it down!!!!!!!!!
  602.         move.w    8(a5),d5
  603.         cmp.w    #856,d5        ;too low??
  604.         ble    newvals
  605.         move.w    #856,d5        ;too low.
  606.         move.w    d5,8(a5)
  607.         bra    newvals
  608. ;    *********************************************************
  609. nofx02:        tst.b    d6
  610.         bne.s    nofx00
  611. ;    **************************************** Effect 00 ******
  612.         tst.b    d4    ;both fxqualifiers are 0s: no arpeggio!!
  613.         beq.w    endl
  614.         move.b    (a5),d1
  615.         bsr.w    DoArpeggio
  616.         subq.b    #1,d4        ;-1 to make it 0 - 127
  617.         add.b    3290(a4),d4    ;add play transpose
  618.         clr.w    d0
  619.         move.b    1(a5),d0    ;prev. instr #
  620.         mulu    #48,d0        ;get address of this sample's data
  621.         add.b    51(a4,d0.w),d4    ;add instrument transpose
  622.         lsl.b    #1,d4        ;shift to make index for UWORD
  623.         lea    _periodit,a1
  624.         move.w    0(a1,d4.w),d5
  625.         bra.w    newvals
  626. ;    *********************************************************
  627. nofx00:        cmp.b    #$0d,d6
  628.         beq.s    fx0d
  629.         cmp.b    #$0a,d6
  630.         bne.s    nofx0d
  631. ;    **************************************** Effect 0D/0A ***
  632. fx0d:        btst    #5,3291(a4)
  633.         beq.s    nostD
  634.         move.b    3293(a4),d0
  635.         cmp.b    _counter,d0
  636.         ble.w    endl
  637. nostD:        move.b    d4,d1
  638.         move.b    2(a5),d0    ;move previous vol to d0
  639.         and.b    #$f0,d1
  640.         bne.s    crescendo
  641.         sub.b    d4,d0    ;sub from prev. vol
  642.         bpl.s    novolund0
  643.         clr.b    d0    ;volumes under zero not accepted!!!
  644. novolund0:    move.b    d0,2(a5)    ;put new vol back
  645.         move.b    d0,d1
  646.         bra    dispvolchng
  647. crescendo:    lsr.b    #4,d1
  648.         add.b    d1,d0
  649.         cmp.b    #64,d0
  650.         ble.s    novolover64
  651.         moveq.l    #64,d0
  652. novolover64:    move.b    d0,2(a5)
  653.         move.b    d0,d1
  654.         bra.w    dispvolchng
  655. ;    *********************************************************
  656. nofx0d:        cmp.b    #5,d6
  657.         bne.s    nofx05
  658. ;    **************************************** Effect 05 ******
  659.         move.w    8(a5),d5 ;this is very simple: get the old period
  660.         cmp.b    #3,_counter    ;and..
  661.         bge.w    newvals        ;if counter < 3
  662.         sub.w    d4,d5    ;subtract effect qualifier
  663.         bra.w    newvals
  664. ;    *********************************************************
  665. nofx05:        cmp.b    #$03,d6
  666.         bne.s    nofx03
  667. ;    **************************************** Effect 03 ******
  668.         btst    #5,3291(a4)
  669.         beq.s    nost3
  670.         move.b    3293(a4),d0
  671.         cmp.b    _counter,d0
  672.         ble.w    endl
  673. nost3:        move.w    20(a5),d0    ;d0 = target period
  674.         beq.w    newvals    ;no target period specified
  675.         move.w    8(a5),d1    ;d1 = curr. period
  676.         move.b    7(a5),d4    ;get prev. speed
  677.         cmp.w    d0,d1
  678.         bhi.s    subper    ;curr. period > target period
  679.         add.w    d4,d1    ;add the period
  680.         cmp.w    d0,d1
  681.         bge.s    targreached
  682.         bra.s    targnreach
  683. subper:        sub.w    d4,d1    ;subtract
  684.         cmp.w    d0,d1
  685.         bgt.s    targnreach
  686. targreached:    move.w    20(a5),d1 ;eventually push target period
  687.         clr.w    20(a5) ;now we can forget everything
  688. targnreach:    move.w    d1,8(a5)
  689.         move.w    d1,d5
  690.         bra.w    newvals
  691. ;    *********************************************************
  692. nofx03:        cmp.b    #$0c,d6
  693.         bne.s    nofx0c
  694.         tst.b    _counter
  695.         bne.w    endl
  696.         move.b    2(a5),d1
  697. dispvolchng:    move.w    d7,d0
  698.         ext.w    d1
  699.         jsr    SetDisp3(pc)
  700.         bra.w    newvals
  701. ;    *********************************************************
  702. nofx0c:        cmp.b    #$04,d6
  703.         bne.s    nofx04
  704. ;    **************************************** Effect 04 ******
  705.         tst.b    d4
  706.         beq.s    nonvib
  707.         move.b    d4,23(a5)
  708. nonvib:        move.b    22(a5),d0
  709.         lsr.b    #2,d0
  710.         and.w    #$1f,d0
  711.         clr.w    d1
  712.         move.b    sinetable(pc,d0.w),d1
  713.         move.b    23(a5),d0
  714.         and.w    #$000f,d0
  715.         mulu    d0,d1
  716.         lsr.w    #6,d1
  717.         move.w    8(a5),d5
  718.         tst.b    22(a5)
  719.         bmi.s    subvib
  720.         add.w    d1,d5
  721.         bra.s    nsubvib
  722. subvib:        sub.w    d1,d5
  723. nsubvib:        move.b    23(a5),d0
  724.         lsr.b    #2,d0
  725.         and.b    #$3c,d0
  726.         add.b    d0,22(a5)
  727.         bra.w    newvals
  728. sinetable:    dc.b $00,$18,$31,$4a,$61,$78,$8d,$a1,$b4,$c5,$d4,$e0,$eb,$f4,$fa,$fd
  729.         dc.b $ff,$fd,$fa,$f4,$eb,$e0,$d4,$c5,$b4,$a1,$8d,$78,$61,$4a,$31,$18
  730. ;    *********************************************************
  731. nofx04:        cmp.b    #$0f,d6
  732.         bne.w    nofx0f
  733. ;    **************************************** Effect 0F ******
  734. fx0f:        cmp.b    #$ff,d4
  735.         bne.s    no0fff
  736.         move.w    d7,d0
  737.         bsr.w    _ChannelOff
  738.         bra.w    endl
  739. no0fff:        cmp.b    #$f1,d4
  740.         bne.s    no0ff1
  741.         cmp.b    #3,_counter
  742.         bne.w    endl
  743.         bra.s    playfxnote
  744. no0ff1:        cmp.b    #$f2,d4
  745.         bne.s    no0ff2
  746.         cmp.b    #3,_counter
  747.         bne.w    endl
  748.         bra.s    playfxnote
  749. no0ff2:        cmp.b    #$f3,d4
  750.         bne.s    no0ff3
  751.         move.b    _counter,d0
  752.         and.b    #2+4,d0        ;is 2 or 4
  753.         beq.s    endl
  754. playfxnote:    lea    4(a4),a3    ;skip "MED\x04"
  755.         clr.w    d0
  756.         move.b    1(a5),d0
  757.         mulu    #48,d0        ;get address of this sample's data
  758.         adda.w    d0,a3        ;a3 contains now address of it
  759.         move.w    d7,d0        ;track # to d0...
  760.         clr.w    d1
  761.         move.b    (a5),d1        ;get note # of previous note
  762.         clr.w    d2
  763.         move.b    2(a5),d2    ;get previous volume
  764.         clr.w    d3
  765.         move.b    1(a5),d3    ;and prev. sample #
  766.         bsr    _SoitaNuotti
  767.         bra.s    endl
  768. no0ff3:        cmp.b    #$f8,d4        ;f8 = filter off
  769.         beq.s    filteroff
  770.         cmp.b    #$f9,d4        ;f9 = filter on
  771.         bne.s    endl
  772.         bclr    #1,$bfe001
  773.         bra.s    setfiltspcupd
  774. filteroff:    bset    #1,$bfe001
  775. setfiltspcupd:    or.b    #1,_specialupd
  776.         bra.s    endl
  777. ;    *********************************************************
  778. nofx0f:        cmp.b    #$0c,d6
  779.         bne.s    endl
  780. newvals:        tst.w    d5    ;now: do the effects!!!
  781.         beq.s    oldper
  782.         move.w    d7,d4
  783.         jsr    SetDisp2(pc)
  784.         bra.s    nooldper
  785. oldper:        move.w    8(a5),d5 ;no new period specified: get the old
  786. nooldper:    movea.l    10(a5),a1    ;get channel address
  787.         move.w    d5,ac_per(a1)    ;push period
  788.         clr.w    d5
  789.         move.b    2(a5),d5    ;get volume
  790.         move.w    d5,ac_vol(a1)    ;and push it
  791. endl:        addq.b    #1,d7    ;increment channel number
  792.         cmp.w    numtracks(pc),d7    ;all channels done???
  793.         blt.w    trloop1    ;not yet!!!
  794.  
  795.         bsr    _StartDMA    ;turn on DMA
  796.         move.b    3291(a4),d0    ;get the flags
  797.         btst    #1,d0        ;is Topi's jumping on ???
  798.         beq.s    exitint        ;no
  799.         lea    animcnt(pc),a1
  800.         lea    animpause(pc),a2
  801.         btst    #2,d0        ;every 8th note ???
  802.         beq.s    no8th
  803.         moveq    #7,d0
  804.         and.w    _pline,d0    ;is this 8th note ??
  805.         bne.s    no8th        ;no...
  806.         tst.b    (a1)
  807.         bne.s    no8th
  808.         tst.w    _pstate
  809.         beq.s    no8th
  810.         move.b    #1,(a1)
  811. no8th:        tst.b    (a1)
  812.         beq.s    exitint
  813.         addq.b    #1,(a2)    ;Handles all animation
  814.         cmp.b    #2,(a2)
  815.         blt.s    exitint
  816.         cmp.b    #10,(a1)
  817.         bne.s    nojumpend
  818.         clr.b    (a1)
  819.         move.b    #1,(a2)
  820.         bra.s    exitint
  821. nojumpend:    clr.w    d0
  822.         move.b    (a1),d0
  823.         addq.b    #1,(a1)
  824.         lsl.w    #2,d0
  825.         lea    frame(pc),a1
  826.         move.l    0(a1,d0.w),_sprptr
  827.         tst.w    _updscrflag
  828.         beq.s    exitint
  829. sigjump:        movea.l    _maintsk,a1    ;and asks the main task to...
  830.         move.l    _hyppymsk,d0    ;...SetPointer() !!!!!
  831.         jsr    -$144(a6)    ;Signal()
  832.         clr.b    (a2)
  833. exitint:        movem.l    (sp)+,d2-d7/a2-a5
  834.         rts
  835. _SetTempo:    move.w    d0,_tempo
  836.         cmp.b    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  837.         bhi.s    calctempo
  838.         subq.b    #1,d0
  839.         move.b    d0,_song+3293
  840.         lsl.w    #1,d0
  841.         move.w    sttempo+2(pc,d0.w),d1
  842.         bra.s    pushtempo
  843. calctempo:    move.l    #470000,d1
  844.         divu    d0,d1
  845. pushtempo:    movea.l    craddr+4(pc),a0
  846.         move.b    d1,(a0)        ;and set the CIA timer
  847.         lsr.w    #8,d1
  848.         movea.l    craddr+8(pc),a0
  849.         move.b    d1,(a0)
  850.         or.b    #4,_specialupd
  851.         rts    ; vv-- These values are the SoundTracker tempos (approx.)
  852. sttempo:    dc.w    $0f00,2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  853.  
  854. midifx:        cmp.b    #1,d6
  855.         bne.s    nomidi01fx
  856.         lea    prevmidipbend(pc),a0
  857.         clr.w    d1
  858.         move.b    3(a5),d1    ;get previous midi channel
  859.         lsl.w    #1,d1        ;UWORD index
  860.         tst.b    d4        ;x100??
  861.         beq.s    resetpbend
  862.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  863.         lsl.w    #3,d4        ;multiply bend value by 8
  864.         add.w    d4,d0
  865.         cmp.w    #$3fff,d0
  866.         bls.s    bendpitch
  867.         move.w    #$3fff,d0
  868. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  869.         lsr.b    #1,d1        ;back to UBYTE
  870.         or.b    #$e0,d1
  871.         lea    noteondata(pc),a0
  872.         move.b    d1,(a0)        ;midi command & channel
  873.         move.b    d0,1(a0)    ;lower value
  874.         and.b    #$7f,1(a0)    ;clear bit 7
  875.         lsr.w    #7,d0
  876.         and.b    #$7f,d0        ;clr bit 7
  877.         move.b    d0,2(a0)    ;higher 7 bits
  878.         moveq.l    #3,d0
  879.         bsr.w    _AddMIDIData
  880.         bra.w    endl
  881. nomidi01fx:    cmp.b    #2,d6
  882.         bne.s    nomidi02fx
  883.         lea    prevmidipbend(pc),a0
  884.         clr.w    d1
  885.         move.b    3(a5),d1
  886.         lsl.w    #1,d1
  887.         tst.b    d4
  888.         beq.s    resetpbend    ;x200??
  889.         move.w    0(a0,d1.w),d0
  890.         lsl.w    #3,d4
  891.         sub.w    d4,d0
  892.         bpl.s    bendpitch    ;not under 0
  893.         clr.w    d0
  894.         bra.s    bendpitch
  895. resetpbend:    tst.b    _counter
  896.         bne.w    endl
  897.         move.w    #$2000,d0
  898.         bra.s    bendpitch
  899. nomidi02fx:    cmp.b    #$04,d6
  900.         bne.s    nomidi04fx
  901.         moveq    #$01,d0
  902.         bra.s    pushctrldata
  903. nomidi04fx:    cmp.b    #$0e,d6        ;with MIDI, this is "pan", when
  904.         bne.s    nomidi0efx    ;values are 0 - $7f
  905.         moveq    #$0a,d0
  906. pushctrldata:    tst.b    _counter    ;do it only once in a note
  907.         bne.w    endl        ;(when counter = 0)
  908.         lea    noteondata(pc),a0 ;push "control change" data,
  909.         move.b    3(a5),(a0)      ;d0 = 1. databyte, d4 = 2. db
  910.         or.b    #$b0,(a0)
  911.         move.b    d0,1(a0)
  912.         move.b    d4,2(a0)
  913.         bmi.w    endl    ;I said 0 - $7f!!! (for future compability)
  914.         moveq.l    #3,d0
  915.         bsr.w    _AddMIDIData
  916.         bra.w    endl
  917. nomidi0efx:    cmp.b    #$0f,d6
  918.         bne.w    endl
  919.         cmp.b    #$fa,d4        ;hold pedal ON
  920.         bne.s    nomffa
  921.         moveq    #$40,d0
  922.         moveq    #$7f,d4
  923.         bra.s    pushctrldata
  924. nomffa:        cmp.b    #$fb,d4        ;hold pedal OFF
  925.         bne.s    nomffb
  926.         moveq    #$40,d0
  927.         moveq    #$00,d4
  928.         bra.s    pushctrldata
  929. nomffb:        bra.w    fx0f
  930.  
  931. DoArpeggio:    ; begin note in d1, note num returned in d4
  932.         move.b    _counter,d0
  933.         tst.b    d0
  934.         beq.s    arpg03
  935.         cmp.b    #3,d0
  936.         bne.s    arpgn03
  937. arpg03:        and.b    #$0f,d4        ;counter = 0 or 3: get last number
  938.         add.b    d1,d4        ;add it to note number
  939.         rts
  940. arpgn03:        cmp.b    #1,d0
  941.         beq.s    arpg14
  942.         cmp.b    #4,d0
  943.         bne.s    arpgn14
  944. arpg14:        lsr.b    #4,d4    ;counter = 1 or 4: get the first number
  945.         add.b    d1,d4    ;add to prev. note
  946.         rts
  947. arpgn14:    move.b    d1,d4    ;2 or 5: the previous note
  948.         rts
  949.  
  950. _ResetMIDI:    movem.l    d2/a2,-(sp)
  951.         lea    prevmidicpres(pc),a0
  952.         clr.l    (a0)+    ;force presets to be set again
  953.         clr.l    (a0)+    ;(clear prev. preset numbers)
  954.         clr.l    (a0)+
  955.         clr.l    (a0)+
  956.         clr.b    lastcmdbyte
  957.         lea    midiresd(pc),a2
  958.         move.b    #$e0,(a2)    ;reset pitchbenders & mod. wheel
  959.         move.b    #$b0,3(a2)
  960.         moveq.l    #15,d2
  961. respbendl:    movea.l    a2,a0
  962.         moveq.l    #6,d0
  963.         bsr.w    _AddMIDIData
  964.         addq.b    #1,(a2)
  965.         addq.b    #1,3(a2)
  966.         dbf    d2,respbendl
  967.         lea    prevmidipbend(pc),a2
  968.         moveq.l    #15,d2
  969. resprevpbends:    move.w    #$2000,(a2)+
  970.         dbf    d2,resprevpbends
  971.         movem.l    (sp)+,d2/a2
  972.         rts
  973. midiresd:    dc.b    $e0,$00,$40,$b0,$01,$00
  974.  
  975.         even
  976. getinsdata:    clr.l    d2
  977.         move.w    4(a0),d0    ;Soitin-struct in a0, instr#<<1: d3
  978.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  979.         move.l    a0,d0
  980.         lea    _periodit,a0
  981.         lsl.b    #1,d1
  982.         move.w    0(a0,d1.w),d5 ;put period to d5
  983.         move.l    d0,a0
  984.         addq.l    #6,d0        ;Skip structure
  985.         move.l    (a0),d1        ;length
  986.         move.w    40(a3),d2
  987.         move.w    42(a3),d3
  988.         rts
  989. iff5or3oct:    movem.l    a1/d6-d7,-(sp)
  990.         clr.l    d7
  991.         move.w    d1,d7
  992.         divu    #12,d7    ;octave #
  993.         move.l    d7,d5
  994.         swap    d5    ;note number in this oct (0-11) is in d5
  995.         move.l    (a0),d1
  996.         cmp.b    #2,d0
  997.         bne.s    no3oct
  998.         addq.l    #6,d7
  999.         divu    #7,d1    ;get length of the 1st octave
  1000.         bra.s    no5oct
  1001. no3oct:        divu    #31,d1    ;get length of the 1st octave (5 octaves)
  1002. no5oct:        move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  1003.         move.w    40(a3),d2
  1004.         move.w    42(a3),d3
  1005.         clr.w    d6
  1006.         move.b    shiftcnt(pc,d7.w),d6
  1007.         lsl.w    d6,d2
  1008.         lsl.w    d6,d3
  1009.         lsl.w    d6,d1
  1010.         move.b    mullencnt(pc,d7.w),d6
  1011.         mulu    d6,d0        ;offset of this oct from 1st oct
  1012.         add.l    a0,d0        ;add base address to offset
  1013.         addq.l    #6,d0        ;skip structure
  1014.         lea    _periodit,a1
  1015.         add.b    octstart(pc,d7.w),d5
  1016.         lsl.b    #1,d5
  1017.         move.w    0(a1,d5.w),d5
  1018.         movem.l    (sp)+,a1/d6-d7
  1019.         rts    ;returns period in d5
  1020. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0
  1021. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0
  1022. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36
  1023.  
  1024.         xref    _ciaaresource
  1025.         xref    _maintsk
  1026.  
  1027. _AudioInit:    movem.l    a6/d2,-(sp)
  1028.         clr.l    d2
  1029.         movea.l    4,a6
  1030. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ alloc signal bit
  1031.         addq.l    #1,d2
  1032.         st.l    d0    ; -1
  1033.         jsr    -$14a(a6)    ;AllocSignal()
  1034.         tst.b    d0
  1035.         bmi.w    initerr
  1036.         move.b    d0,sigbitnum
  1037. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ prepare IORequest
  1038.         lea    allocport(pc),a1
  1039.         move.b    d0,15(a1)    ;set mp_SigBit
  1040.         move.l    _maintsk,16(a1)    ;set mp_SigTask
  1041.         lea    reqlist(pc),a0
  1042.         move.l    a0,(a0)        ;NEWLIST begins...
  1043.         addq.l    #4,(a0)
  1044.         clr.l    4(a0)
  1045.         move.l    a0,8(a0)    ;NEWLIST ends...
  1046. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ open audio.device
  1047.         addq.l    #1,d2
  1048.         lea    allocreq(pc),a1
  1049.         lea    audiodevname(pc),a0
  1050.         clr.l    d0
  1051.         clr.l    d1
  1052.         movea.l    4,a6
  1053.         jsr    -$1bc(a6)    ;OpenDevice()
  1054.         tst.b    d0
  1055.         bne.s    initerr
  1056.         st.b    audiodevopen
  1057. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ open ciaa.resource
  1058.         addq.l    #1,d2
  1059.         clr.l    d0
  1060.         lea    ciaaname(pc),a1
  1061.         jsr    -$1f2(a6)    ;OpenResource()
  1062.         tst.l    d0
  1063.         beq.s    initerr
  1064.         move.l    d0,_ciaaresource
  1065. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ attach interrupt
  1066.         addq.l    #1,d2
  1067.         move.l    d0,a6
  1068.         lea    timerinterrupt(pc),a1
  1069.         clr.l    d0    ;Bit number 0: Timer A
  1070.         jsr    -$6(a6)    ;AddICRVector
  1071.         tst.l    d0
  1072.         bne.s    initerr
  1073.         lea    craddr(pc),a0
  1074.         move.l    #$bfee01,(a0)+
  1075.         move.l    #$bfe401,(a0)+
  1076.         move.l    #$bfe501,(a0)+
  1077.         and.b    #%10000000,$bfee01
  1078.         st.b    timeropen
  1079.         clr.w    _pstate
  1080.         clr.l    d0
  1081. initret:        movem.l    (sp)+,a6/d2
  1082.         rts
  1083. initerr:        move.l    d2,d0
  1084.         bra.s    initret
  1085.  
  1086. _AudioRem:    move.l    a6,-(sp)
  1087.         tst.b    timeropen
  1088.         beq.s    rem1
  1089. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ remove interrupt
  1090.         move.l    _ciaaresource,a6
  1091.         lea    timerinterrupt(pc),a1
  1092.         moveq.l    #0,d0
  1093.         jsr    -$c(a6)        ;RemICRVector
  1094. rem1:        movea.l    4,a6
  1095.         tst.b    audiodevopen
  1096.         beq.s    rem2
  1097.         move.w    #$000f,$dff096    ;stop audio DMA
  1098. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ close audio.device
  1099.         lea    allocreq(pc),a1
  1100.         jsr    -$1c2(a6)    ;CloseDevice()
  1101. rem2:        clr.l    d0
  1102.         move.b    sigbitnum(pc),d0
  1103.         bmi.s    rem3
  1104. ;    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ free signal bit
  1105.         jsr    -$150(a6)    ;FreeSignal()
  1106. rem3:        move.l    (sp)+,a6
  1107.         rts
  1108.  
  1109. _GetSerial:    move.l    a6,-(sp)    ;Get serial port for MIDI
  1110.         bsr.s    GetSer2
  1111.         tst.l    d0        ;got the port??
  1112.         beq.s    rgser        ;yes
  1113.         movea.l    4,a6        ;no..try to flush serial.device:
  1114.         jsr    -$84(a6)        ;Forbid
  1115.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  1116.         lea    serdev(pc),a1        ;"serial.device"
  1117.         jsr    -$114(a6)        ;FindName
  1118.         tst.l    d0
  1119.         beq.s    serdnotf        ;no serial.device!!
  1120.         move.l    d0,a1
  1121.         jsr    -$1b6(a6)        ;RemDevice
  1122. serdnotf:    jsr    -$8a(a6)        ;and Permit
  1123.         bsr.s    GetSer2        ;now try it again...
  1124. rgser:        move.l    (sp)+,a6
  1125.         rts
  1126.  
  1127. GetSer2:        movea.l    4,a6
  1128.         clr.l    d0
  1129.         lea    miscresname(pc),a1
  1130.         jsr    -$1f2(a6)    ;OpenResource()
  1131.         move.l    d0,miscresbase
  1132.         tst.l    d0
  1133.         beq.s    gserror
  1134.         move.l    d0,a6
  1135.         lea    medname(pc),a1
  1136.         clr.l    d0        ;serial port
  1137.         jsr    -$6(a6)        ;AllocMiscResource()
  1138.         tst.l    d0
  1139.         bne.s    gserror
  1140.         st.b    serportalloc
  1141.         clr.w    intrson
  1142.         move.w    $dff01c,d0
  1143.         btst    #0,d0
  1144.         sne.b    intrson
  1145.         btst    #11,d0
  1146.         sne.b    intrson+1
  1147.         moveq.l    #0,d0        ;TBE
  1148.         lea    serinterrupt(pc),a1
  1149.         move.l    4,a6
  1150.         jsr    -$a2(a6)    ;SetIntVector()
  1151.         move.l    d0,prevtbe
  1152.         moveq.l    #11,d0        ;RBF
  1153.         lea    rbfinterrupt(pc),a1
  1154.         jsr    -$a2(a6)    ;SetIntVector()
  1155.         move.l    d0,prevrbf
  1156.         move.w    #$8001,$dff09a    ;TBE on!!
  1157.         move.w    #114,$dff032    ;set baud rate (SERPER)
  1158.         clr.l    d0
  1159.         rts
  1160. gserror:        st    d0
  1161.         rts
  1162.  
  1163. intrson:        dc.b    0,0
  1164.  
  1165. _FreeSerial:    move.l    a6,-(sp)
  1166.         tst.l    miscresbase
  1167.         beq.s    retfs
  1168.         tst.b    serportalloc
  1169.         beq.s    retfs
  1170.         move.w    #$0801,$dff09a    ;disable RBF & TBE
  1171.         movea.l    prevtbe(pc),a1
  1172.         moveq.l    #0,d0
  1173.         movea.l    4,a6
  1174.         jsr    -$a2(a6)    ;SetIntVector()
  1175.         movea.l    prevrbf(pc),a1
  1176.         moveq.l    #11,d0
  1177.         jsr    -$a2(a6)    ;SetIntVector()
  1178.         move.w    #$8000,d0
  1179.         tst.b    intrson
  1180.         beq.s    nofsstbe
  1181.         bset    #0,d0
  1182. nofsstbe:    tst.b    intrson+1
  1183.         beq.s    nofssrbf
  1184.         bset    #11,d0
  1185. nofssrbf:    move.w    d0,$dff09a    ;set RBF & TBE to their prev. values
  1186.         movea.l    miscresbase(pc),a6
  1187.         clr.l    d0        ;serial port
  1188.         jsr    -$c(a6)        ;FreeMiscResource()
  1189.         clr.b    serportalloc
  1190.         clr.b    lastcmdbyte
  1191. retfs:        move.l    (sp)+,a6
  1192.         rts
  1193.  
  1194. prevtbe:    dc.l    0
  1195. prevrbf:    dc.l    0        
  1196.         xref    _recmidi
  1197.         xref    _recmidimsk
  1198.         xref    _recvol
  1199.  
  1200. RBFIntHandler:    move.w    $18(a0),d0    ;SERDATR
  1201.         move.w    #$0800,$9c(a0)    ;clr intreq
  1202.         btst    #7,d0        ;status??
  1203.         beq.s    nostatus
  1204.         move.b    d0,(a1)
  1205.         move.b    #$1,3(a1)
  1206.         rts
  1207. nostatus:    clr.w    d1
  1208.         move.b    3(a1),d1
  1209.         move.b    d0,0(a1,d1.w)
  1210.         addq.b    #1,d1
  1211.         cmp.b    #3,d1
  1212.         bge.s    sigmidirec
  1213.         move.b    d1,3(a1)
  1214.         rts
  1215. sigmidirec:    move.b    #$1,3(a1)
  1216.         and.b    #$f0,(a1)
  1217.         cmp.b    #$90,(a1)
  1218.         bne.s    nosrec
  1219.         move.b    1(a1),_recmidi
  1220.         move.b    2(a1),_recvol
  1221.         movea.l    _maintsk,a1
  1222.         move.l    _recmidimsk,d0
  1223.         jsr    -$144(a6)    ;Signal()
  1224. nosrec:        rts
  1225. recmidi:        dc.b    0,0,0,0
  1226.         
  1227. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable...
  1228.         addq.b    #1,$126(a6)
  1229.         move.w    #1,$9c(a0)    ;clear intreq bit
  1230.         move.b    bytesinbuff(pc),d0
  1231.         beq.s    exsih        ;buffer empty
  1232.         movea.l    4(a1),a5    ;get buffer read pointer
  1233.         move.w    #$100,d1    ;Stop bit
  1234.         move.b    (a5),d1        ;get byte
  1235.         move.w    d1,$30(a0)    ;and push it out!! (SERDAT)
  1236.         addq.l    #1,a5        ;add 1
  1237.         cmpa.l    a1,a5        ;shall we reset ptr??
  1238.         bne.s    norrbuffptr    ;not yet..
  1239.         lea    sendbuffer(pc),a5
  1240. norrbuffptr:    subq.b    #1,d0        ;one less bytes in buffer
  1241.         move.b    d0,bytesinbuff    ;remember it
  1242.         move.l    a5,4(a1)    ;push new read pointer back
  1243. exsih:        subq.b    #1,$126(a6)
  1244.         bge.s    exsih0
  1245.         move.w    #$c000,$9a(a0)
  1246. exsih0:        rts
  1247.  
  1248. _AddMIDIData:    tst.b    serportalloc
  1249.         beq.s    retamd
  1250.         movem.l    a2/a6,-(sp)
  1251.         movea.l    4,a6
  1252.         move.w    #$4000,$dff09a    ;Disable interrupts
  1253.         addq.b    #1,$126(a6)    ;ExecBase->IDNestCnt
  1254.         move.b    bytesinbuff(pc),d1
  1255.         bne.s    noTBEreq
  1256.         move.w    #$8001,$dff09c    ;request TBE
  1257. noTBEreq:    lea    buffptr(pc),a2    ;end of buffer (ptr)
  1258.         movea.l    (a2),a1        ;buffer pointer
  1259. adddataloop:    move.b    (a0)+,d1    ;get byte
  1260.         bpl.s    norscheck    ;this isn't a status byte
  1261.         cmp.b    #$ef,d1        ;forget system messages
  1262.         bhi.s    norscheck
  1263.         cmp.b    lastcmdbyte(pc),d1 ;same as previos status byte??
  1264.         beq.s    samesb        ;yes, skip
  1265.         move.b    d1,lastcmdbyte    ;no, don't skip but remember!!
  1266. norscheck:    move.b    d1,(a1)+    ;push it to midi send buffer
  1267.         addq.b    #1,bytesinbuff
  1268. samesb:        cmpa.l    a2,a1    ;end of buffer??
  1269.         bne.s    noresbuffptr    ;no, no!!
  1270.         lea    sendbuffer(pc),a1 ;better reset it to avoid trashing
  1271. noresbuffptr:    subq.b    #1,d0
  1272.         bne.s    adddataloop
  1273.         move.l    a1,(a2)        ;push new buffer ptr back
  1274. overflow:    subq.b    #1,$126(a6)
  1275.         bge.s    retamd1
  1276.         move.w    #$c000,$dff09a    ;enable interrupts again
  1277. retamd1:        movem.l    (sp)+,a2/a6
  1278. retamd:        rts
  1279. sendbuffer:    ds.b    128
  1280. buffptr:        dc.l    sendbuffer
  1281. readbuffptr:    dc.l    sendbuffer
  1282. miscresbase:    dc.l    0
  1283. lastcmdbyte:    dc.b    0
  1284.         even
  1285. preschgdata:    dc.b    0,0
  1286. noteondata:    dc.l    0
  1287. audiodevopen:    dc.b    0
  1288. timeropen:    dc.b    0
  1289. serportalloc:    dc.b    0
  1290. bytesinbuff:    dc.b    0
  1291. sigbitnum:    dc.b    -1
  1292.         even
  1293. craddr:        dc.l    0
  1294.         dc.l    0    ;tloaddr
  1295.         dc.l    0    ;thiaddr
  1296. timerinterrupt:    dc.w    0,0,0,0,0
  1297.         dc.l    timerintname,0,_IntHandler
  1298. serinterrupt:    dc.w    0,0,0,0,0
  1299.         dc.l    serintname,buffptr,SerIntHandler
  1300. rbfinterrupt:    dc.w    0,0,0,0,0
  1301.         dc.l    rbfintname,recmidi,RBFIntHandler
  1302. allocport:    dc.l    0,0    ;succ, pred
  1303.         dc.b    4,0    ;NT_MSGPORT
  1304.         dc.l    0    ;name
  1305.         dc.b    0,0    ;flags = PA_SIGNAL
  1306.         dc.l    0    ;task
  1307. reqlist:    dc.l    0,0,0    ;list head, tail and tailpred
  1308.         dc.b    5,0
  1309. allocreq:    dc.l    0,0
  1310.         dc.b    5,127    ;NT_MESSAGE, use maximum priority (127)
  1311.         dc.l    0,allocport    ;name, replyport
  1312.         dc.w    68        ;length
  1313.         dc.l    0    ;io_Device
  1314.         dc.l    0    ;io_Unit
  1315.         dc.w    0    ;io_Command
  1316.         dc.b    0,0    ;io_Flags, io_Error
  1317.         dc.w    0    ;ioa_AllocKey
  1318.         dc.l    sttempo    ;ioa_Data
  1319.         dc.l    1    ;ioa_Length
  1320.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  1321.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  1322. ciaaname:    dc.b    'ciaa.resource',0
  1323. timerintname:    dc.b    'MEDTimerInterrupt',0
  1324. serintname:    dc.b    'MEDSerialInterrupt',0
  1325. rbfintname:    dc.b    'MEDSerialRBFInt',0
  1326. audiodevname:    dc.b    'audio.device',0
  1327. miscresname:    dc.b    'misc.resource',0
  1328. serdev:        dc.b    'serial.device',0
  1329. medname:        dc.b    'MED',0 ;yeah, our name
  1330.         end
  1331.