home *** CD-ROM | disk | FTP | other *** search
/ Dave Lowe: Intro 1 of 2 Adlib / Lowe_Intro1of2Adlib.img / DRIVERS / ADLIB.NEW < prev    next >
Encoding:
Text File  |  1993-01-22  |  19.2 KB  |  1,134 lines

  1. ;--------------------------------------------------------------------------------
  2. ;
  3. ;AdLib specific routines
  4. ;--------------------------------------------------------------------------------
  5.  
  6. ;--------------------------------------------------------------------------------
  7. ;PlaySongAdLib
  8. ;
  9. ;plays a song from the list
  10. ;after setting up all voices
  11. ;
  12. ;Inputs:
  13. ;
  14. ;ax:    Song No.
  15. ;
  16. ;--------------------------------------------------------------------------------
  17.  
  18. PlaySongAdLib proc near
  19.     sub    al,15        ;seventeen roland files in front
  20.     mov    currentSong,ax
  21.     mov    bx,ax
  22.     shl    bx,1
  23.  
  24. ;transfer song parameters
  25. ;to AdLib driver
  26.     mov    ax,ds
  27.     mov    es,ax
  28.  
  29.     mov    si,SongAdNVoices[bx]
  30.     mov    di,offset ChanNVoices
  31.     mov    cx,8
  32.     rep movsb
  33.  
  34.     mov    si,SongAdCVoices[bx]
  35.     mov    di,offset ChanVoices
  36.     mov    cx,8*4
  37.     rep movsb
  38.     
  39.     mov    si,SongAdPatches[bx]
  40.     mov    di,offset SongV0
  41.     mov    cx,8
  42.     rep movsb
  43.  
  44.     mov    si,SongAdTransp[bx]
  45.     mov    di,offset AdTransposes
  46.     mov    cx,9
  47.     rep movsb
  48.  
  49.     shr    bx,1
  50.     mov    al,SongAdPercs[bx]
  51.     mov    Percussion,al
  52.  
  53. ;initialise AdLib
  54.  
  55.     call    InitAdLib
  56.     call    WriteGlobals
  57.     call    InitAllVoices
  58.  
  59. ;Set up voices for this song
  60.  
  61.     mov    si,offset SongV0
  62.     call    SetUpSongVoices
  63.  
  64.     mov    MusicPlayFlg,0
  65.     call    InstallTimer
  66.  
  67.  
  68.     mov    ax,csongseg1
  69.     mov    es,ax
  70.     mov     ax,[playptr]
  71.     mov    si,ax        ;offset MIDIPlayBuffer1
  72.     mov    bx,1        ;  files are midi time stretched for right speed
  73.     mov    al,SongTempos[bx]
  74.     xor    ah,ah
  75.     call    PlayMIDIFileAdLib
  76.  
  77.     ret
  78. PlaySongAdLib endp
  79.  
  80. ;--------------------------------------------------------------------------------
  81. ;routines for playing MIDI files on AdLib
  82. ;--------------------------------------------------------------------------------
  83.  
  84. ;--------------------------------------------------------------------------------
  85. ;PlayMIDIFileAdLib
  86. ;
  87. ;Inputs:
  88. ;
  89. ;es:si    pointer to MIDI file start
  90. ;ax    temp beats per min.
  91. ;
  92. ;plays until end of file or 
  93. ;until StopMIDIPlayAdLib is called
  94. ;
  95. ;--------------------------------------------------------------------------------
  96.  
  97. PlayMIDIFileAdLib proc near
  98.     mov    PlaySeg,es
  99.     mov    PlayPtr,si
  100.  
  101.     mov    Tempo,ax
  102.     call    SetTimerTempo
  103.  
  104.     call    ReadMIDIHeader    ;get all header info
  105.  
  106.     mov    si,PlayPtr
  107.     call    GetVarLength    ;get first delay
  108.     mov    ax,10
  109.     mov    PlayPtr,si
  110.  
  111.     mov    cs:EventDelay,1
  112.     mov    MusicPlayFlg,-1
  113.  
  114.     ret
  115. PlayMIDIFileAdLib endp
  116.  
  117. StopMIDIPlayAdLib proc near
  118.     mov    MusicPlayFlg,0
  119.     call    RemoveTimer
  120.     call    AllNotesOff
  121.     call    InitAdLib
  122.     ret
  123. StopMIDIPlayAdLib endp
  124.  
  125. SetTimerTempo proc near
  126.     mul    TicksPQ        ;ticks per min.
  127.     mov    bx,60
  128.     div    bx        ;ticks per second
  129.     mov    bx,ax
  130.     mov    ax,13089    ;1192737Hz basic freq.
  131.     mov    dx,18          
  132.     div    bx
  133.     or     ax,1          
  134.     call    TimerRate    ;set up interrupt rate
  135.     ret
  136. SetTimerTempo endp
  137.  
  138. ;--------------------------------------------------------------------------------
  139. ;EventRoutine:
  140. ;
  141. ;This routine is called after (EventDelay) interrupts
  142. ;
  143. ;returns:
  144. ;
  145. ;ax:    new EventDelay
  146. ;
  147. ;--------------------------------------------------------------------------------
  148.  
  149. EventRoutine proc near
  150.     cmp    MusicPlayFlg,0
  151.     jne    DoEvents
  152.     mov    ax,1        ;not playing yet
  153.     ret
  154. DoEvents:
  155.     cmp    BoardFlg,0
  156.     jne    ContEvents        ;play music on ADLIB BOARD
  157. ;    
  158. ;        must be music or fx on ROLAND                   
  159. ;
  160.     cmp    fx_flag,0
  161.     je    rol_music    
  162.     ;jmp    rol_fx_driver
  163. rol_music:
  164.     jmp    RolEventRoutine        ;play music on ROLAND BOARD
  165. ContEvents:
  166.  
  167. ;do current event
  168.  
  169.     cld
  170.     mov    es,PlaySeg
  171.     mov    si,PlayPtr
  172.  
  173.     cmp    byte ptr es:[si],080h
  174.     jb    ProcessMIDIEvent    ;using running status
  175.  
  176.     mov    al,es:[si]
  177.     inc    si
  178.  
  179.     cmp    al,0FFh
  180.     jne    NotAMeta
  181.     mov    al,es:[si]    ;Meta event type
  182.     inc    si
  183.     call    ProcessMetaEvent
  184.     cmp    ax,0
  185.     je    JND
  186.     jmp    DoneAMPlay    ;end of track
  187. JND:    jmp    NextDelay
  188. NotAMeta:
  189.  
  190.     cmp    al,0F0h
  191.     jb    NotASE
  192.     call    ProcessSysEx0
  193.     jmp    NextDelay
  194. NotASE:
  195.  
  196.     mov    MIDIStatus,al
  197.  
  198. ProcessMIDIEvent:
  199.     mov    al,MIDIStatus
  200.     mov    bl,al
  201.     and    al,1111b    ;channel
  202.     mov    MIDIChannel,al
  203.     xor    bh,bh
  204.     mov    cl,4
  205.     shr    bx,cl        ;form index
  206.     mov    cl,MIDIDataSizes[bx]
  207.     xor    ch,ch
  208.     mov    MIDIDataSiz,cx
  209.  
  210. ;handle different midi events
  211.  
  212. voff:    cmp    bx,8h    ;note off
  213.     jne    NMidi8
  214.  
  215.     mov    bl,MidiChannel
  216.     xor    bh,bh
  217.  
  218.     cmp    Percussion,0
  219.     je    NoOffPerc
  220.     cmp    bx,9
  221.     jne    NoOffPerc
  222.     jmp    NMidiE    ;no note off for percussion voices
  223. NoOffPerc:
  224.  
  225. ;find which voice carries the note to turn off
  226.  
  227.     mov    cl,ChanNVoices[bx]
  228.     xor    ch,ch
  229.  
  230.     shl    bx,1
  231.     shl    bx,1
  232.     shl    bx,1    ;index into ChanVoices
  233.  
  234.     cmp    cx,0
  235.     jne    VAllocd
  236.     jmp    NMidiE        ;no voices allocated
  237. VAllocd:
  238.     cmp    cx,1
  239.     je    NoOChoice
  240. PolyNOL:
  241.     mov    dl,ChanVoices[bx]
  242.     xor    dh,dh
  243.     mov    di,dx
  244.     mov    dl,VoiceNotes[di]
  245.     cmp    dl,es:[si]    ;is it this note?
  246.     je    GotOffVoice    ;yes it is
  247.     inc    bx
  248.     loop    PolyNOL        ;keep trying
  249. GotOffVoice:
  250.     mov    ax,di        ;this voice
  251.  
  252. UseNoteOff:
  253.     mov    bl,es:[si]
  254.     mov    cl,es:[si+1]
  255.     call    NoteOff
  256.     jmp    NMidiE
  257. NoOChoice:
  258.     mov    al,ChanVoices[bx]    ;the only one
  259.     jmp    UseNoteOff
  260.  
  261. NMidi8:
  262. ;**********************
  263.     push ax
  264.     push bx
  265.     inc si
  266.     mov al,es:[si]
  267.     cmp al,0
  268.     jne isnoteon
  269. bkp:    pop bx
  270.     pop ax
  271.     mov bx,8h
  272.     dec si
  273.     jmp voff
  274. isnoteon:
  275.     dec si
  276.     pop bx    
  277.     pop ax
  278. ;***********************
  279.     cmp    bx,9h    ;note on
  280.     je    HNoteOn
  281.     jmp    NMidi9
  282. HNoteOn:
  283.  
  284. ;handle polyphony
  285. ;- scan available voices
  286. ;- if none free use earliest played
  287.  
  288.     mov    bl,MidiChannel
  289.     xor    bh,bh
  290.  
  291.     mov    di,bx
  292.     shl    di,1
  293.     inc    MIDIChanCount[di]
  294.  
  295.     cmp    Percussion,0
  296.     je    NoPercMidi
  297.     cmp    bx,9        ;midi channel 10 is percussion channel
  298.     je    HandlePerc
  299. NoPercMidi:
  300.     mov    cl,ChanNVoices[bx]
  301.     xor    ch,ch
  302.  
  303.     shl    bx,1
  304.     shl    bx,1
  305.     shl    bx,1    ;index into ChanVoices
  306.  
  307.     cmp    cx,0
  308.     jne    VNAllocd
  309.     jmp    NMidiE        ;no voices allocated
  310. VNAllocd:
  311.     cmp    cx,1
  312.     je    NoPChoice
  313.     mov    bp,0FFFFh    ;this will contain earliest voice
  314.     xor    ax,ax        ;voice to use
  315. PolyVL:
  316.     mov    dl,ChanVoices[bx]    ;is this voice free?
  317.     xor    dh,dh
  318.     mov    di,dx
  319.     shl    di,1
  320.     mov    dx,VoiceStatus[di]
  321.     cmp    dx,0
  322.     je    GotVoice        ;yes, it's free
  323.     cmp    dx,bp
  324.     jae    NotEarlV
  325.     mov    bp,dx        ;this is earlier
  326.     mov    ax,di
  327. NotEarlV:
  328.     inc    bx
  329.     loop    PolyVL        ;keep trying
  330.     shr    ax,1
  331.     jmp    UseVoice    ;use earliest
  332.  
  333. GotVoice:
  334.     mov    ax,di
  335.     shr    ax,1
  336. UseVoice:
  337. ;    mov    bx,ax
  338. ;    xor    bh,bh
  339. ;    mov    bl,AdTransposes[bx]    ;use transpose
  340.     mov    bl,es:[si]
  341.     mov    cl,es:[si+1]
  342.     push    ax
  343.     push    bx
  344.     push    cx
  345.     call    NoteOff
  346.     pop    cx
  347.     pop    bx
  348.     pop    ax
  349.     call    NoteOn
  350.     jmp    NMidiE
  351.  
  352. NoPChoice:
  353.     mov    al,ChanVoices[bx]    ;the only one
  354.     jmp    UseVoice
  355.  
  356. HandlePerc:
  357. ;deal with percussion sounds
  358.     mov    bl,es:[si]    ;note no.
  359.     sub    bl,35        ;form index
  360.     mov    al,DrumSounds[bx]
  361.     mov    bl,24
  362.     jmp    UseVoice
  363.  
  364. NMidi9:         
  365.     cmp    bx,0Ah    ;note aftertouch
  366.     jne    NMidiA
  367.     jmp    NMidiE
  368. NMidiA:
  369.     cmp    bx,0Bh    ;control change
  370.     jne    NMidiB
  371.     jmp    NMidiE
  372. NMidiB:
  373.     cmp    bx,0Ch    ;program change
  374.     jne    NMidiC
  375.     jmp    NMidiE
  376. NMidiC:
  377.     cmp    bx,0Dh    ;chan. aftertouch
  378.     jne    NMidiD
  379.     jmp    NMidiE
  380. NMidiD:
  381.     cmp    bx,0Eh    ;pitch wheel
  382.     jne    NMidiE
  383.     jmp    NMidiE
  384. NMidiE:
  385.  
  386.     add    si,MIDIDataSiz
  387.  
  388. NextDelay:
  389.  
  390. ;check for end of tune
  391.  
  392.     mov    bx,si
  393.     sub    bx,StartPtr
  394.     cmp    bx,PlayLength
  395.     jae    DoneAMPlay
  396. play_aagain:
  397.     call    GetVarLength    ;get delay to next event
  398.     mov    PlayPtr,si
  399.     ret
  400.  
  401. DoneAMPlay:
  402.  
  403.     mov ax,[loop_flag]
  404.     cmp ax,0
  405.     je noloop    
  406.  
  407.     mov    si,startptr
  408.     jmp    play_aagain
  409. noloop:
  410.     call allnotesoff
  411.     mov    MusicPlayFlg,0
  412.     mov    ax,0
  413.     ret
  414.  
  415. EventRoutine endp
  416.  
  417. ;--------------------------------------------------------------------------------
  418. ;routines for playing notes on AdLib
  419. ;--------------------------------------------------------------------------------
  420.  
  421. ;--------------------------------------------------------------------------------
  422. ;NoteOn
  423. ;
  424. ;inputs:
  425. ;
  426. ;al:    voice    0-8 in melodic 0-10 in percussion mode
  427. ;bl:    pitch    0-127 midi notes: 60 is Middle C (48 is AdLib mid C)
  428. ;cl:    volume    0-127
  429. ;--------------------------------------------------------------------------------
  430.  
  431. NoteOn proc near
  432.     push    si
  433.     push    es
  434.     xor    ah,ah
  435.     xor    bh,bh
  436.     mov    si,ax
  437.     mov    VoiceVolumes[si],cl
  438.     mov    VoiceNotes[si],bl
  439.     add    bl,AdTransposes[si]
  440.     shl    si,1
  441.     mov    dx,PlayPtr
  442.     mov    VoiceStatus[si],dx    ;flag it on
  443.  
  444.     sub    bx,12    ;adlib pitch = midi pitch-12    
  445.     jge    NoteOK
  446.     xor    bx,bx
  447. NoteOK:
  448.     mov    cx,2000h
  449.     cmp    Percussion,0
  450.     jne    PercNoteOn
  451. NormNoteOn:
  452.     mov    dx,1    ;note on
  453.     call    WriteAdLibFreq
  454.     pop    es
  455.     pop    si
  456.     ret
  457.  
  458. ;deal with percussion voices
  459.  
  460. PercNoteOn:
  461.     cmp    ax,5
  462.     jle    NormNoteOn    ;not a perc
  463.     push    ax
  464.     
  465.     cmp    ax,BD        ;change bass drum freq.
  466.     je    BFreq
  467.  
  468.     cmp    ax,TC        ;can't change TC and HH freq
  469.     je    WrBits
  470.     cmp    ax,HH
  471.     je    WrBits
  472.     cmp    ax,SD        ;influenced by TOM
  473.     je    WrBits
  474.  
  475.     push    ax
  476.     push    bx
  477.     push    cx
  478.     mov    ax,SD
  479.     add    bx,7        ;pitch SD = pitch TOM+7
  480.     mov    dx,0
  481.     call    WriteAdLibFreq
  482.     pop    cx
  483.     pop    bx
  484.     pop    ax
  485.  
  486. BFreq:
  487.     mov    dx,0        ;must be 0 for percussion
  488.     call    WriteAdLibFreq
  489.  
  490. WrBits:    pop    bx
  491.     sub    bx,6        ;get offset
  492.     mov    al,PerckeyOns[bx]    ;bit to set
  493.     or    PercBits,al
  494.     call    WriteAmVibPerc    ;set perc bit
  495.     pop    es
  496.     pop    si
  497.     ret
  498. NoteOn endp
  499.  
  500. ;--------------------------------------------------------------------------------
  501. ;NoteOff
  502. ;
  503. ;inputs:
  504. ;
  505. ;ax:    voice    0-8 in melodic 0-10 in percussion mode
  506. ;bl:    pitch    0-127 midi notes: 60 is Middle C (48 is AdLib mid C)
  507. ;cl:    volume    0-127
  508. ;--------------------------------------------------------------------------------
  509.  
  510. NoteOff proc near
  511.     push    si
  512.     push    es
  513.     xor    ah,ah
  514.     xor    bh,bh
  515.     mov    si,ax
  516.     mov    VoiceVolumes[si],cl
  517.     mov    VoiceNotes[si],bl
  518.     add    bl,AdTransposes[si]
  519.     shl    si,1
  520.     mov    VoiceStatus[si],0    ;flag it off
  521.  
  522.     sub    bx,12    ;adlib pitch = midi pitch-12    
  523.     jge    NoteOKO
  524.     xor    bx,bx
  525. NoteOKO:
  526.     mov    cx,2000h
  527.     xor    dx,dx    ;voice off
  528.     cmp    Percussion,0
  529.     jne    PercNoteOff
  530. NormNoteOff:
  531.     call    WriteAdLibFreq
  532.     pop    es
  533.     pop    si
  534.     ret
  535. PercNoteOff:
  536.     cmp    ax,5
  537.     jle    NormNoteOff    ;not a perc
  538.     mov    bx,ax
  539.     sub    bx,6        ;get offset
  540.     mov    al,PerckeyOns[bx]    ;bit to clear
  541.     not    al
  542.     and    PercBits,al
  543.     call    WriteAmVibPerc    ;clear perc bit
  544.     pop    es
  545.     pop    si
  546.     ret
  547. NoteOff endp
  548.  
  549. ;--------------------------------------------------------------------------------
  550. ;AllNotesOff
  551. ;
  552. ;turns off all voices
  553. ;
  554. ;--------------------------------------------------------------------------------
  555.  
  556. AllNotesOff proc near
  557.     mov    bp,8
  558.     xor    ax,ax
  559.     cmp    Percussion,0
  560.     je    NoteOLp
  561.     mov    bp,10
  562. NoteOLp:
  563.     push    ax
  564.     push     bp
  565.     call    NoteOff
  566.     pop    bp
  567.     pop    ax
  568.     inc    ax
  569.     cmp    ax,bp
  570.     jle    NoteOLp
  571.     ret
  572. AllNotesOff endp
  573.  
  574. ;--------------------------------------------------------------------------------
  575. ;routines for setting parameters in AdLib
  576. ;--------------------------------------------------------------------------------
  577.  
  578. ;--------------------------------------------------------------------------------
  579. ;
  580. ;InitAdLib:
  581. ;
  582. ;clear all AdLib registers
  583. ;
  584. ;--------------------------------------------------------------------------------
  585.  
  586. InitAdLib proc near
  587.     mov    ax,1
  588. IAdLp:    push    ax
  589.     call    AdLibWrite    ;clear all reg.s
  590.     pop    ax
  591.     inc    al
  592.     cmp    al,0F5h
  593.     jle    IAdLp
  594.  
  595.     mov    al,4
  596.     mov    ah,60h        ;reset Timer-1 & 2
  597.     call    AdLibWrite
  598.     mov    al,4
  599.     mov    ah,80h        ;reset Timer-1 & 2
  600.     call    AdLibWrite
  601.  
  602.     mov    al,1
  603.     mov    ah,00100000b    ;enable wave-select
  604.     call    AdLibWrite
  605.  
  606.     ret
  607. InitAdLib endp
  608.  
  609. ;--------------------------------------------------------------------------------
  610. ;
  611. ;InitAllVoices:
  612. ;
  613. ;set up all slots to default
  614. ;
  615. ;--------------------------------------------------------------------------------
  616.  
  617. InitAllVoices proc near
  618.     mov    si,offset pianoOpr0
  619.     mov    di,offset pianoOpr1
  620.     mov    ax,0
  621.  
  622.     mov    bp,8    ;last voice
  623.     cmp    Percussion,0
  624.     je    LoopIS
  625.     mov    bp,5    ;last voice
  626.  
  627. LoopIS:    push    ax
  628.     push    bp
  629.     call    WriteVoice        ;set up voices 0-8
  630.     pop    bp
  631.     pop    ax
  632.     inc    ax
  633.     cmp    ax,bp
  634.     jle    LoopIS
  635.  
  636.     cmp    Percussion,0
  637.     je    QuitIS
  638. SetUpPerc:
  639.     mov    si,offset bdOpr0    ;set up percussion voices
  640.     mov    di,offset bdOpr1
  641.     mov    ax,6
  642.     call    WriteVoice
  643.     mov    si,offset sdOpr
  644.     mov    ax,7
  645.     call    WriteVoice
  646.     mov    si,offset tomOpr
  647.     mov    ax,8
  648.     call    WriteVoice
  649.     mov    si,offset cymbOpr
  650.     mov    ax,9
  651.     call    WriteVoice
  652.     mov    si,offset hhOpr
  653.     mov    ax,10
  654.     call    WriteVoice
  655. QuitIS:
  656.     ret
  657. InitAllVoices endp
  658.  
  659. ;--------------------------------------------------------------------------------
  660. ;SetUpSongVoices
  661. ;
  662. ;set up all voices for a song
  663. ;
  664. ;si:    array of patch no.s for voices
  665. ;
  666. ;--------------------------------------------------------------------------------
  667.  
  668. SetUpSongVoices proc near
  669.     mov    ax,0
  670.  
  671.     mov    bp,8    ;last voice
  672.     cmp    Percussion,0
  673.     je    LoopSV
  674.     mov    bp,5    ;last voice
  675.  
  676. LoopSV:    push    ax
  677.     push    bp
  678.     push    si
  679.     mov    bl,[si]    ;patch
  680.     xor    bh,bh
  681.     shl    bx,1
  682.     mov    si,AdLibPatches[bx]
  683.     mov    di,si
  684.     add    di,14        ;operator 1
  685.     call    WriteVoice
  686.     pop    si
  687.     pop    bp
  688.     pop    ax
  689.  
  690.     inc    si
  691.     inc    ax
  692.     cmp    ax,bp
  693.     jle    LoopSV
  694.  
  695.     cmp    Percussion,0
  696.     je    NoSPerc
  697.     call    SetUpPerc
  698. NoSPerc:
  699.     ret
  700.  
  701. SetUpSongVoices endp
  702.  
  703. ;--------------------------------------------------------------------------------
  704. ;WriteVoice:
  705. ;
  706. ;sets up a voice for a patch
  707. ;
  708. ;ax: voice
  709. ;si: patch operator0
  710. ;di: patch operator1
  711. ;
  712. ;--------------------------------------------------------------------------------
  713.  
  714. WriteVoice proc near
  715.     push    si
  716.     mov    bx,offset VoiceSlots
  717.     cmp    Percussion,0
  718.     je    VNPerc
  719.     mov    bx,offset VoiceSlotsPerc    ;for percussion mode
  720. VNPerc:
  721.     mov    dx,ax        ;voice
  722.     shl    ax,1
  723.     add    bx,ax
  724.     mov    al,[bx]        ;first slot (modulator)
  725.     push    bx
  726.     push    dx
  727.     push    di
  728.     mov    bx,dx        ;voice
  729.     call    WriteSlot
  730.     pop    di
  731.     pop    dx
  732.     pop    bx
  733.     
  734.     cmp    byte ptr [bx+1],0    ;no second slot (carrier) if <0
  735.     jl    NoWriS
  736.  
  737.     push    bx
  738.     push    dx
  739.     push    di
  740.     call    WriteFeedFM    ;only once per voice
  741.     pop    di
  742.     pop    dx
  743.     pop    bx
  744.  
  745.     mov    si,di        ;operator1
  746.     mov    al,[bx+1]    ;second slot (carrier)
  747.     mov    bx,dx        ;voice
  748.     call    WriteSlot
  749.  
  750. NoWriS:
  751.     pop    si
  752.     ret
  753. WriteVoice endp
  754.  
  755. ;--------------------------------------------------------------------------------
  756. ;WriteSlot:
  757. ;
  758. ;sets the AdLib up for:
  759. ;
  760. ;ax: slot
  761. ;bx: voice
  762. ;si: operator
  763. ;
  764. ;--------------------------------------------------------------------------------
  765.  
  766. WriteSlot proc near
  767.     mov    Voice,bl
  768.     mov    bx,ax
  769.     xor    bh,bh
  770.     mov    bl,SlotOffsets[bx]    ;offset within chip
  771.  
  772. ;make sure all params within range
  773.  
  774.     and    byte ptr KSL[si],3
  775.     and    byte ptr MULTI[si],15
  776.     and    byte ptr FB[si],7
  777.     and    byte ptr AR[si],15
  778.     and    byte ptr SL[si],15
  779.     and    byte ptr EG[si],1
  780.     and    byte ptr DR[si],15
  781.     and    byte ptr RR[si],15
  782.     and    byte ptr TL[si],63
  783.     and    byte ptr AM[si],1
  784.     and    byte ptr VIB[si],1
  785.     and    byte ptr KSR[si],1
  786.     and    byte ptr C[si],1
  787.     and    byte ptr WS[si],3
  788.  
  789. ;set Ksl,Level
  790.  
  791.      mov    ah,KSL[si]
  792.     mov    cl,6
  793.     shl    ah,cl
  794.     mov    al,TL[si]
  795.     or    ah,al
  796.     mov    al,40h
  797.     add    al,bl
  798.     call    AdLibWrite
  799.  
  800. ;set Attack,Decay
  801.  
  802.     mov    ah,AR[si]
  803.     mov    cl,4
  804.     shl    ah,cl
  805.     or    ah,DR[si]
  806.     mov    al,60h
  807.     add    al,bl
  808.     call    AdLibWrite
  809.  
  810. ;set Sustain,Release
  811.  
  812.     mov    ah,SL[si]
  813.     mov    cl,4
  814.     shl    ah,cl
  815.     or    ah,RR[si]
  816.     mov    al,80h
  817.     add    al,bl
  818.     call    AdLibWrite
  819.  
  820. ;AM, VIB, EG-TYP (Sustaining), KSR, MULTI
  821.  
  822.     mov    ah,AM[si]
  823.     mov    cl,7
  824.     shl    ah,cl
  825.     mov    al,VIB[si]
  826.     mov    cl,6
  827.     shl    al,cl
  828.     or    ah,al
  829.     mov    al,EG[si]
  830.     mov    cl,5
  831.     shl    al,cl
  832.     or    ah,al
  833.     mov    al,KSR[si]
  834.     mov    cl,4
  835.     shl    al,cl
  836.     or    ah,al
  837.     or    ah,MULTI[si]
  838.     mov    al,20h
  839.     add    al,bl
  840.     call    AdLibWrite
  841.  
  842. ;Wave Select
  843.  
  844.     mov    ah,WS[si]
  845.     mov    al,0E0h
  846.     add    al,bl
  847.     call    AdLibWrite
  848.  
  849.     ret
  850. WriteSlot endp
  851.  
  852.  
  853. ;set Feedback,Fm
  854. ;-only once per voice
  855.  
  856. WriteFeedFM proc near
  857.     mov    ah,FB[si]
  858.     shl    ah,1
  859.     mov    al,C[si]
  860.     xor    al,1
  861.     or    ah,al
  862. ;    or    ah,C[si]
  863.     mov    al,0C0h
  864.     add    al,Voice
  865.     call    AdLibWrite
  866.     ret
  867. WriteFeedFM endp
  868.  
  869. ;-------------------------------------------------------------------------------
  870. ;WriteGlobals:
  871. ;
  872. ;sets up AdLib global parameters
  873. ;
  874. ;WriteAmVibPerc:
  875. ;
  876. ;sets the values: amplitude depth,vibrato depth,percussion and percussion keyons
  877. ;
  878. ;-------------------------------------------------------------------------------
  879.  
  880. WriteGlobals proc near
  881.     call    WriteAmVibPerc
  882.     mov    ah,NoteSel
  883.     mov    cl,6
  884.     shl    ah,cl
  885.     mov    al,08h
  886.     call    AdLibWrite
  887.     ret
  888. WriteGlobals endp
  889.  
  890. WriteAmVibPerc proc near
  891.     mov    ah,AmDepth
  892.     mov    cl,7
  893.     shl    ah,cl
  894.     mov    al,VibDepth
  895.     mov    cl,6
  896.     shl    al,cl
  897.     or    ah,al
  898.     mov    al,Percussion
  899.     mov    cl,5
  900.     shl    al,cl
  901.     or    ah,al
  902.     or    ah,PercBits
  903.     mov    al,0BDh
  904.     call    AdLibWrite
  905.     ret
  906. WriteAmVibPerc endp
  907.  
  908. ;------------------------------------------------------------
  909. ;WriteAdLibFreq
  910. ;
  911. ;set a voice's frequency
  912. ;
  913. ;inputs:
  914. ;    ax:    voice        (0-8)
  915. ;    bx:    note        (0-95)
  916. ;    cx:    pitchbend    (0-4000h, 2000h no bend)
  917. ;    dx:    keyOn        (0 disable 1 enable)
  918. ;
  919. ;sets volume to VoiceVolumes[voice] if keyOn=1
  920. ;
  921. ;------------------------------------------------------------
  922.  
  923. WriteAdLibFreq proc near
  924.     mov    Voice,al
  925.     mov    Note,bl
  926.     mov    PitchBend,cx
  927.  
  928.     mov    ax,cx
  929.  
  930.     mov    cl,5
  931.     shl    dl,cl        ;shift KON to correct location
  932.     mov    keyOn,dl
  933.  
  934.     push    ax
  935.     cmp    dl,0
  936.     je    NoVV        ;not if keyon=0
  937. ;set voice volume
  938.     jmp    NoVV
  939.  
  940.     mov    bx,offset VoiceSlots
  941.     cmp    Percussion,0
  942.     je    NoVVPerc
  943.     mov    bx,offset VoiceSlotsPerc
  944.     cmp    Voice,6
  945.     jle    NoVVPerc
  946.     dec    bx        ;for single op. percussion
  947. NoVVPerc:
  948.     mov    al,Voice
  949.     xor    ah,ah
  950.     shl    ax,1
  951.     add    bx,ax
  952.     mov    bl,[bx+1]    ;carrier slot
  953.     xor    bh,bh
  954.     mov    al,SlotOffsets[bx]
  955.     mov    bl,Voice
  956.     mov    ah,VoiceVolumes[bx]
  957.     shr    ah,1        ;0-63 volume
  958.     shr    ah,1        ;0-31
  959.     shr    ah,1        ;0-15
  960.     neg    ah
  961.     add    ah,15        ;attenuation
  962.     add    al,40h
  963.     call    AdLibWrite
  964.     
  965. NoVV:    pop    ax
  966.  
  967.     sub    ax,2000h    ;convert pitch bend to signed no.
  968.     je    NoMul        ;no mul if =0
  969.  
  970.     sar    ax,1        ;scale to 0-255
  971.     sar    ax,1
  972.     sar    ax,1
  973.     sar    ax,1
  974.     sar    ax,1
  975.  
  976.     imul    PitchBendRange    ;* by pitch bend range
  977.  
  978. NoMul:    add    ah,Note        ;add on note no.
  979.  
  980.     add    ax,8        ;round to nearest 1/16
  981.  
  982.     sar    ax,1        ;scale to 4 bit fix point
  983.     sar    ax,1
  984.     sar    ax,1
  985.     sar    ax,1
  986.  
  987.     jge    Not0    ;<0?
  988.  
  989.     xor    ax,ax        ;=0
  990.     jmp    Not95
  991.  
  992. Not0:    cmp    ax,(96*16)-1    ;note <=95?
  993.     jl    Not95
  994.  
  995.     mov    ax,(96*16)-1    ;=95
  996. Not95:
  997.     mov    di,ax        ;get half-tone value within 1 octave
  998.     shr    di,1        ;use integer part of note MOD 12
  999.     shr    di,1
  1000.     shr    di,1
  1001.     shr    di,1
  1002.     mov    dx,di
  1003.     mov    bl,MOD12Tab[di]
  1004.     xor    bh,bh
  1005.     mov    di,bx
  1006.  
  1007.     shl    di,1        ;get offset in frequency table
  1008.     shl    di,1
  1009.     shl    di,1
  1010.     shl    di,1
  1011.     shl    di,1
  1012.  
  1013.     shl    ax,1
  1014.     and    ax,31
  1015.     add    di,ax        ;add in fractional part (lower 4 bits)
  1016.  
  1017.     mov    ax,FNumTable[di]    ;get frequency
  1018.  
  1019.     mov    di,dx            ;get octave number
  1020.     mov    bl,DIV12Tab[di]    ;DIV 12
  1021.     dec    bl
  1022.  
  1023.     or    ax,ax        ;if high bit set must inc octave
  1024.     jge    NoIncO
  1025.     inc    bl
  1026. NoIncO:
  1027.     or    bl,bl        ;check for <0
  1028.     jge    BlokOK
  1029.     inc    bl
  1030.     sar    ax,1        ;must /2
  1031. BlokOK:
  1032.  
  1033. ;finally write frequency info to AdLib
  1034.  
  1035.     push    bx        ;save block
  1036.     push    ax        ;save freq value
  1037.     mov    ah,al
  1038.     mov    al,FNUM_LOW
  1039.     add    al,Voice
  1040.     call    AdLibWrite
  1041.     pop    ax
  1042.     pop    bx
  1043.  
  1044.     mov    al,ah        ;set up for register
  1045.     and    al,3
  1046.     shl    bl,1
  1047.     shl    bl,1
  1048.     add    al,bl
  1049.     add    al,keyOn
  1050.     mov    ah,al
  1051.     mov    al,KEYON_BLOCK_FNUM
  1052.     add    al,Voice
  1053.     call    AdLibWrite
  1054.     ret
  1055.  
  1056. WriteAdLibFreq endp
  1057.  
  1058. ;------------------------------------------------------------
  1059. ;AdLibWrite
  1060. ;
  1061. ;write to AdLib board
  1062. ;
  1063. ;input:    al - Register No.
  1064. ;    ah - Data
  1065. ;
  1066. ;delays an appropriate amount of
  1067. ;time for AdLib hardware to catch up:
  1068. ;
  1069. ;  3.3 æsec after a register select write
  1070. ; 23.0 æsec after a data write
  1071. ;
  1072. ;------------------------------------------------------------
  1073.  
  1074. AdLibWrite proc near
  1075.  
  1076.     mov    dx,ADLIB_ADDR    ;AdLib output port
  1077.     out    dx,al
  1078.                 ;at least 12 cycles delay (3.3 æsec at 3.6 Mhz)
  1079.     in    al,dx
  1080.     in    al,dx
  1081.     in    al,dx
  1082.     in    al,dx
  1083.     in    al,dx
  1084.     in    al,dx
  1085.  
  1086.     inc    dx        ;data reg
  1087.     mov    al,ah
  1088.     out    dx,al
  1089.     dec    dx
  1090.                 ;84 cycles delay (23 æsec at 3.6 Mhz)
  1091.     in    al,dx
  1092.     in    al,dx
  1093.     in    al,dx
  1094.     in    al,dx
  1095.     in    al,dx
  1096.     in    al,dx
  1097.     in    al,dx
  1098.     in    al,dx
  1099.     in    al,dx
  1100.     in    al,dx
  1101.  
  1102.     in    al,dx
  1103.     in    al,dx
  1104.     in    al,dx
  1105.     in    al,dx
  1106.     in    al,dx
  1107.     in    al,dx
  1108.     in    al,dx
  1109.     in    al,dx
  1110.     in    al,dx
  1111.     in    al,dx
  1112.  
  1113.     in    al,dx
  1114.     in    al,dx
  1115.     in    al,dx
  1116.     in    al,dx
  1117.     in    al,dx
  1118.     in    al,dx
  1119.     in    al,dx
  1120.     in    al,dx
  1121.     in    al,dx
  1122.     in    al,dx
  1123.  
  1124.     in    al,dx
  1125.     in    al,dx
  1126.     in    al,dx
  1127.     in    al,dx
  1128.     in    al,dx
  1129.  
  1130.     ret
  1131.  
  1132. AdLibWrite endp
  1133.  
  1134.