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