home *** CD-ROM | disk | FTP | other *** search
/ Dave Lowe: Krustys SFX Ad Libs / Lowe_KrustysSFXAdLibs.img / DISKSENT / FXDRIVE.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-11-27  |  55.7 KB  |  2,702 lines

  1. ;***************************************************************************
  2.  
  3. DEBUG   equ 0   ;debug conditional assembly
  4. NOCOUNT equ 0   ;interrupt counter conditional assembly
  5.  
  6. ;****************************************************************************
  7. _TEXT segment byte public  'code'    
  8.  
  9.     assume CS:_TEXT
  10.     assume DS:_TEXT
  11.  
  12. extrn      MasterTable:byte,_PatchTable:byte
  13.  
  14. public    _NoWrites
  15.     
  16. ;----------------------------------------------------------------------------
  17. ;function pointer table (for indirect function calls if used)
  18. public functable
  19. functable    dw    _Init_Sound_ISR
  20.         dw    _Terminate_Sound_ISR
  21.         dw    _Sound_ISR
  22.         dw    _sendsnd
  23.         dw    _speak
  24.         dw    _sstatus
  25.         dw    _vstatus
  26.         dw    _getaddr
  27.         dw    _setmotor
  28.         dw    _abortsample
  29.         dw    _switchsoundtable
  30. tablelen    equ    ($-functable)/4
  31. ;----------------------------------------------------------------------------
  32. include fxdrive.inc
  33. include pbend.inc
  34.  
  35. MaxWrites    dw    0    
  36. _NoWrites    dw    0
  37.     
  38. installedur db    0    ;ddt 6/9/90
  39.  
  40.  ;sound system global variables
  41. Old8255        db    0    ;timer 2 control
  42. Mask8255        db    0    ;timer 2 control 
  43. curchannel        db    0    ;current channel being parsed
  44. do_sound        db    0    ;run sound system flag
  45. DrumMask        db    0
  46. globalTempo    db    0    ;global music tempo
  47. motorflag        db    0    ;motor active flag
  48. motordur        db    01    ;current motor duration count
  49. motordcnt        db    01    ;count timer for motor duration
  50. NoiseIndex        dw     0ffffh    
  51. seed            dw    1234h    ;for random number
  52. state        db    0    ;register shadow for motor
  53. ShadowBD        db    0    ;shadow of am/vib/drum reg
  54. YamOff        db    0    ;chip operator offset
  55. Kickshadow        db    0    ;shadow of kick attenuation
  56. Snareshadow     db    0    ;shadow of snare attenuation
  57. Hihatshadow    db    0    ;shadow of hihat attenuation
  58. Tomshadow        db    0    ;shadow of tom attenuation
  59. Rideshadow        db    0    ;shadow of ride attenuation
  60.  
  61. KickMaster        db    0    ;shadow of kick attenuation
  62. SnareMaster     db    0    ;shadow of snare attenuation
  63. HihatMaster    db    0    ;shadow of hihat attenuation
  64. TomMaster        db    0    ;shadow of tom attenuation
  65. RideMaster        db    0    ;shadow of ride attenuation
  66.  
  67. KickAttn        db    0    ;shadow of kick attenuation
  68. SnareAttn         db    0    ;shadow of snare attenuation
  69. HihatAttn        db    0    ;shadow of hihat attenuation
  70. TomAttn        db    0    ;shadow of tom attenuation
  71. RideAttn        db    0    ;shadow of ride attenuation
  72.  
  73. notesync        db    0    ;for sync start of channel
  74. notecntr        db    0    ;for sync start of channel
  75. presync        db    0ffh    ;for sync start of channel
  76. syncbyte        db    0    ;for sync start of channel
  77. synchi        db    0    ;for sync start of channel
  78.  
  79. DurTablePtr    dw    ?
  80. PitchTablePtr    dw    ?
  81. SoundTablePtr    dw    ?
  82.  
  83.  ;old interrupt vectors
  84. OldIntOFF        dw    0    ;from sound sys
  85. OldIntSEG        dw    0
  86. OldIntOFF2        dw    0    ;from speech int
  87. OldIntSEG2        dw    0
  88.  
  89.  ;interrupt vars
  90. SoundSysTick    db    12    ;interrupt divider
  91. TimerTick        db    48    ;another interrupt divider
  92. TickOffset        dw    0    ;pointer to external time base
  93. TickSeg        dw    0    ;other half of pointer
  94.  
  95. ;variables for speech interrupt
  96. evenodd        db    0
  97. lastsample        db    0
  98. dlength        dw    0
  99. doffset        dw    0
  100. dsegment        dw    0
  101. dbaseaddr        dw    0
  102. SampleFlag        db    0
  103.  
  104. buffhead        dw    ?    ;for sound code queue
  105. bufftail        dw    ?    ;for sound code queue
  106. buff            db    16 dup(?)    ;sound code queue
  107.  
  108. spram1        db  SPRAMLEN dup(?)    ;sound processor ram
  109. spram2        db  SPRAMLEN dup(?)
  110. spram3        db  SPRAMLEN dup(?)
  111. spram4        db  SPRAMLEN dup(?)
  112. spram5        db  SPRAMLEN dup(?)
  113. spram6        db  SPRAMLEN dup(?)
  114. spram7        db  SPRAMLEN dup(?)
  115. spram8        db  SPRAMLEN dup(?)
  116. spram9        db  SPRAMLEN dup(?)
  117. spram10        db  SPRAMLEN dup(?)
  118.  
  119. schnlPtr        dw  spram1        ;sound channel pointers
  120.             dw  spram2
  121.               dw  spram3
  122.                dw  spram4
  123.                dw  spram5
  124.                dw  spram6
  125.                dw  spram7
  126.                dw  spram8
  127.                dw  spram9
  128.                dw  spram10
  129.  
  130. OPOFFSETS        db  000h
  131. OP2            db  001h
  132. OP3            db  002h
  133. OP4            db  008h
  134. OP5            db  009h
  135. OP6            db  00ah
  136. OP7            db  010h
  137. OP8            db  011h
  138. OP9            db  012h
  139.  
  140. FreqTable        dw  0269h/2        ;c
  141.             dw  028eh/2        ;c#
  142.             dw  02b5h/2        ;d
  143.             dw  02deh/2        ;d#
  144.             dw  0309h/2        ;e
  145.             dw  0338h/2        ;f
  146.             dw  0369h/2        ;f#
  147.             dw  039ch/2        ;g
  148.             dw  03d3h/2        ;g#
  149.             dw  040eh/2        ;a
  150.             dw  044bh/2        ;a#
  151.             dw  048dh/2        ;b
  152.  
  153. ;----------------------------------------------------------------------------
  154. ;sound system interrupt service routine
  155. ;no ins, no outs  restores everything used on exit
  156.  
  157. _newint  proc
  158. public  _newint
  159.  
  160.     push    ax            ;these few pushes to allow more reg variables
  161.     push    bx
  162.     push    dx
  163.     push    ds
  164.  
  165.     mov    ax,cs            ;segment overrides cost two clocks per
  166.     mov    ds,ax            ;assume ds:code recquires this
  167.  
  168.     cmp    motorflag,0        ;motor active ?
  169.     je    no_motor
  170.  
  171.     dec    motordcnt        ;decrement the count
  172.     jnz    no_motor        ;not zero do nothing
  173.  
  174.     mov    bx,offset spram1        ;get offset of spram
  175.     mov    al,[bx+Block]        ;get block of channel 0 in al
  176.     mov    ah,al            ;save al
  177.     and    al,01fh        ;and of gate state
  178.     xor    state,0ffh        ;toggle state
  179.     mov    ah,state
  180.     and    ah,020h        ;isolate gate state
  181.     or    al,ah
  182.     mov    [bx+Block],al        ;save it back
  183.     mov    bl,al
  184.  
  185.     mov    dx,ADLIBREGS        ;card address for regs
  186.     mov    al,0b0h        ;key on/off channel 0
  187.     out    dx,al
  188.     call    Wait33
  189.     mov    al,bl
  190.     inc    dx
  191.     out    dx,al
  192.     call    Wait34
  193.  
  194.     mov    al,motordur        ;reset count
  195.     mov    motordcnt,al
  196.  
  197. no_motor:
  198.     dec    SoundSysTick        ;dec tick counter
  199.     jnz    ni2            ;if zero run sound system
  200.     mov    SoundSysTick,12        ;restore counter
  201.     call    _Sound_ISR        ;service sound every 4th tick
  202.  
  203. if NOCOUNT
  204.     push    ds            ;game time base counter
  205.     lds    bx,dword ptr tickoffset
  206.     add    word ptr [bx],1
  207.     adc    word ptr [bx+2],0
  208.     pop    ds
  209. endif
  210.  
  211. ni2:
  212.     dec    TimerTick        ;dec tick counter
  213.     jnz    ni4            ;if zero service timer interrupt
  214.     mov    TimerTick,48        ;restore counter (every 48th tick)
  215.     pop    ds            ;restore regs b4
  216.     pop    dx
  217.     pop    bx            ;jumping to timer interrupt
  218.     pop    ax
  219.     jmp    dword ptr cs:[oldintOFF]    ;jump to old interrupt
  220.  
  221. ni4:
  222.     mov    al,20h        ;reset interrupt controller
  223.     out    20h,al
  224.  
  225.     pop    ds
  226.     pop    dx
  227.     pop    bx
  228.     pop    ax
  229.     iret
  230.  
  231. _newint  endp
  232. ;----------------------------------------------------------------------------
  233. ;specch driver interrupt service routine
  234. ;speech variables must be setup before this can be used
  235. ;speak routine does all of the setup
  236.  
  237. _newint2  proc 
  238. public  _newint2
  239.  
  240.  
  241.  
  242.     push    ax            ;(15)
  243.     push    dx            ;(15)
  244.     push    ds            ;(10)
  245.     push    si            ;(10)
  246.  
  247.     cmp    cs:SampleFlag,0
  248.     je    stop_sample
  249.  
  250.     lds    si,dword ptr cs:doffset     ;(16+8) pointer to data
  251.     cld                ;(2)    set direction flag
  252.     lodsb
  253.     
  254.     mov    ah,cs:lastsample
  255.     test    cs:evenodd,1        ; even/odd count ??
  256.     je    do_dpcm
  257.  
  258.     shr    al, 1            ; left sampl:
  259.     shr    al, 1
  260.     shr    al, 1
  261.     shr    al, 1
  262.     inc    si            ; increment sampl ptr
  263.  
  264. do_dpcm:
  265.     dec    si
  266.     and    al, 0FH
  267.     test    al, 8            ; test dpcm sign bit
  268.     jne    dpcm_negative
  269.  
  270.     add    ah, al        ; dpcm positive:
  271.     jmp    short do_out
  272.  
  273. dpcm_negative:
  274.     and    al, 7
  275.     sub    ah, al
  276.  
  277. do_out:
  278.     mov    al, ah
  279.     mov    cs:lastsample,ah
  280.     mov    dx,ADLIBDATA
  281.     out    dx,al
  282.     dec    cs:evenodd        ; sampl count --
  283.  
  284.     mov    cs:doffset,si        ;(9+8)  save pointer
  285.     mov    ax,si            ;(8)
  286.     sub    ax,cs:dbaseaddr        ;(9)    
  287.     cmp    ax,cs:dlength        ;(9)
  288.     jb    eoi            ;(16)
  289.     
  290. stop_sample:
  291.     ;**** deinstall interrupt
  292.     mov    al,36h        ;reset timer for 871 Hz operation
  293.      out    TIMERCONTROL,al
  294.     mov    al,055h               ;low byte of divisor for 871Hz
  295.     out    TIMERDATA0,al
  296.     mov    al,05h        ;high byte of divisor
  297.     out    TIMERDATA0,al
  298.  
  299.  
  300.     mov    cs:doffset,0
  301.  
  302.     mov    si,8*4
  303.     xor    ax,ax
  304.     mov    ds,ax
  305.  
  306.     mov    dx,cs:oldintOFF2        ;point interrupt vector
  307.     mov    ax,cs:oldintSEG2        ;back where it belongs
  308.  
  309.     mov    [si],dx
  310.     mov    [si+2],ax
  311.  
  312.     mov    cs:do_sound,0
  313.  
  314. eoi:
  315.     mov    al,20h        ;(4)    reset interrupt controller
  316.     out    20h,al        ;(10)
  317.  
  318.     pop    si            ;(10)
  319.     pop    ds            ;(10)
  320.     pop    dx            ;(15)
  321.     pop    ax            ;(15)
  322.     iret                ;(24)
  323.  
  324. _newint2  endp
  325. ;----------------------------------------------------------------------------
  326. ;initialize sound sytem, install sound interrupt etc.
  327. ;nothing in, nothing out
  328. ; registers are NOT preserved
  329. ;except ds,es,si and di
  330.  
  331. _Init_Sound_ISR    proc far
  332. public    _Init_Sound_ISR
  333.  
  334.     push    ds    
  335.     push    es    
  336.     push    si    
  337.     push    di    
  338.  
  339. if NOCOUNT
  340.     mov cs:tickoffset,ax        ;save location for timer ticks
  341.     mov    ax,ds
  342.     mov    cs:tickseg,ax
  343. endif
  344.  
  345.     mov    ax,cs            ;set ds
  346.     mov    ds,ax
  347.  
  348.     xor    bx,bx
  349.     mov    bx,[bx+offset MasterTable]    ;get address of zero'th sound table
  350.     mov    SoundTablePtr,bx        ;put it in the pointer
  351.  
  352. IF    DEBUG
  353.     mov    MaxWrites,0    
  354.     mov    _NoWrites,0    
  355. ENDIF
  356.  
  357. ;    in  al,P8255        ;get original config
  358. ;    mov Old8255,al      ;save original config
  359.  
  360. ;    and al,NOT (HWGATE2BIT+HWSPKRBIT)
  361.  
  362. ;    out P8255,al
  363. ;    mov     Mask8255,al         ;save it
  364.  
  365.     cli                ;clear interrupts
  366.     mov    ax,3508h        ;dos function number
  367.     int    21h            ;dos get int vector
  368.     mov    oldintSEG,es        ;save segment
  369.     mov    oldintOFF,bx        ;save offset
  370.  
  371.     mov    dx,offset _newint        ;offset of new int handler in dx
  372.     mov    ax,2508h        ;dos function number
  373.     int    21h            ;dos set interrupt vector
  374.  
  375.     call  _initsnd        ;initialize sound variables
  376.  
  377.     mov    al,36h        ;set timer mode
  378.     out    TIMERCONTROL,al        ;send it
  379.     jmp    short it1        ;8253 is a bit slow
  380. it1:
  381.     mov    al,055h        ;low byte of divisor for 871Hz
  382.     out    TIMERDATA0,al
  383.     jmp    short it1a    
  384. it1a:
  385.     mov    al,005h        ;high byte of divisor
  386.     out    TIMERDATA0,al
  387.  
  388.     in    al,021h
  389.     and    al,0feh
  390.     out    021h,al
  391.  
  392.     mov    bufftail,0        ;initialize sound code queue pointers    
  393.     mov    buffhead,0
  394.  
  395.     sti
  396.     pop    di
  397.     pop    si
  398.     pop    es
  399.     pop    ds
  400.  
  401.     ret
  402. _Init_Sound_ISR    endp
  403. ;----------------------------------------------------------------------------
  404. ;un-install sound sytem, un-install sound interrupt, shut off sound chip
  405. ;nothing in, if debug is non-zero function returns number of writes
  406. ;to sound chip in ax
  407. ; registers are NOT preserved
  408. ;except ds,es,si and di
  409.  
  410. _Terminate_Sound_ISR proc far
  411. public _Terminate_Sound_ISR    
  412.  
  413.     push    ds
  414.  
  415.     mov    ax,cs    ;set ds
  416.     mov    ds,ax    ;to cs
  417.  
  418.     push    ds
  419.     cli                ;shut off interrupts
  420.     mov    dx,oldintOFF        ;point interrupt vector
  421.     mov    ax,oldintSEG        ;back where it belongs
  422.     mov    ds,ax            ;dos set interrupt vector
  423.     mov    ax,2508h
  424.     int    21h
  425.     sti
  426.     pop    ds
  427.  
  428.     call    _initsnd        ;clear sound stuff
  429.  
  430.     mov    al,36h        ;reset timer for 18.2 Hz operation
  431.     out    TIMERCONTROL,al
  432.     jmp    short rt1
  433. rt1:
  434.     mov    al,0
  435.     out    TIMERDATA0,al
  436.     jmp    short rt1a
  437. rt1a:
  438.     out    TIMERDATA0,al
  439. IF    DEBUG
  440.     mov    ax,MaxWrites
  441. ENDIF
  442.  
  443.     pop    ds
  444.     ret
  445. _Terminate_Sound_ISR endp    
  446. ;----------------------------------------------------------------------------
  447. ;sound int called by newint calls runsnd
  448. ;this is really here so you can single step thrrough
  449. ;the sound system with a debugger it could be removed
  450.  
  451. _Sound_ISR proc near 
  452. public _Sound_ISR
  453.  
  454.     push    cx
  455.     push    dx
  456.     push    di
  457.     push    si
  458.     
  459.     push    ds
  460.     mov    ax,cs            ;segment overides cost two clocks per
  461.     mov    ds,ax            ;assume ds:code recquires this
  462. IF    DEBUG
  463.     mov    _NoWrites,0    
  464. ENDIF
  465.  
  466.     call     startsound        ;start any sounds in queue
  467.     call     runsnd        ;run sound system 
  468.     call    syncgen        ;run sync generator
  469.     pop    ds
  470.  
  471.     pop    si
  472.     pop    di
  473.     pop    dx
  474.     pop    cx
  475.     ret
  476.  
  477. _Sound_ISR    endp
  478. ;----------------------------------------------------------------------------
  479. ;send sound code to sound system
  480. ;fx number required in ax
  481.  
  482. _sendsnd proc far
  483. public    _sendsnd
  484.  
  485.  
  486.     push    ds
  487.  
  488.     mov    bx,cs                       ;set ds to cs this is 
  489.     mov    ds,bx
  490.  
  491.     mov    bx,buffhead        ;current place in buffer
  492.     mov    [bx+offset buff],ax    ;store in buff
  493.     inc    bx            ;next place
  494.     and    bx,000fh        ;a circular queue
  495.     mov    buffhead,bx        ;save it back
  496.  
  497.     pop    ds
  498.     ret
  499. _sendsnd    endp
  500. ;----------------------------------------------------------------------------
  501. ;called as a part of runsnd
  502. ;actually starts the queued sound codes
  503.  
  504. startsound proc near
  505. public    startsound
  506.  
  507.     ;di  points to sound ram
  508.     ;si points to sound string    
  509.     push    ds
  510.     push    si
  511.     push    di
  512.  
  513.     mov    bx,cs                       ;set ds to cs this is 
  514.     mov    ds,bx                       ;a "com" file
  515.  
  516. nextcode:
  517.     mov    bx,bufftail
  518.     cmp    bx,buffhead        ;head=tail means no codes
  519.     jnz    start_sound_not_done
  520.     jmp    short start_sound_done
  521.  
  522. start_sound_not_done:
  523.     mov    bx,[bx+offset buff]
  524.     sub    bh,bh
  525.     shl    bx,1            ;offset into table x2
  526.     add    bx,SoundTablePtr
  527.     mov    si,[bx]
  528.  
  529.     mov    bx,cs:[si]        ;channel number from string
  530.     cmp    bl,0
  531.     jne    not_channel_zero
  532.     mov    motorflag,0
  533.  
  534. not_channel_zero:
  535.     mov    al,bh            ;al<-priority
  536.     mov    cl,bl            ;cl has channel
  537.     sub    bh,bh            ;bh<-0
  538.     shl    bx,1
  539.     mov    di,[bx+offset SchnlPtr]
  540.  
  541.     cmp    al,[di+Priority]            ;priority not higher or = ?
  542.     jl    nextcode2
  543.  
  544.     call    ClearSpram
  545.     mov    [di+Priority],al        ;this is the new priority
  546.     inc    si            ;skip over channel and 
  547.     inc    si            ;priority bytes
  548.     mov    [di+StrPointer],si    ;ptr to first data in string
  549.     mov    byte ptr [di+Tempo],0ffh    ;reset tempo
  550.     mov    byte ptr [di+TempoCount],0ffh    ;reset tempo
  551.     mov    byte ptr [di+Duration],01h    ;assure use of first op-code
  552.     mov    do_sound,01
  553.  
  554.     cmp    bl,18
  555.     je    nextcode2        ;not in the conductor channel
  556.     call    clearenv
  557.  
  558. nextcode2:
  559.     inc    bufftail
  560.     and    bufftail,000fh
  561.     jmp    nextcode
  562.  
  563. start_sound_done:
  564.     pop    di
  565.     pop    si
  566.     pop    ds
  567.     ret
  568. startsound    endp
  569. ;----------------------------------------------------------------------------
  570. ;sets the motor freq motor freq is on the stack
  571.  
  572. _setmotor    proc far
  573. public    _setmotor
  574.  
  575. _setmotor    endp
  576. ;----------------------------------------------------------------------------
  577. ;stop playing a sample
  578.  
  579. _abortsample    proc far
  580. public    _abortsample
  581.  
  582. _abortsample    endp
  583. ;----------------------------------------------------------------------------
  584. ;switch to a different sound table 
  585. ;the sound table number is on the stack
  586.  
  587. _switchsoundtable    proc far
  588. public    _switchsoundtable
  589.  
  590.     push    bp
  591.     mov    bp,sp
  592.     push    ds
  593.  
  594.  
  595.     mov    bx,cs                       ;set ds to cs this is 
  596.     mov    ds,bx                       ;a "com" file
  597.  
  598.     mov    bx,word ptr [bp+6]
  599.     shl    bx,1
  600.     mov    bx,[bx+offset MasterTable]    ;get address of zero'th sound table
  601.     mov    SoundTablePtr,bx        ;put it in the pointer
  602.     mov    ax,SoundTablePtr
  603.  
  604.     pop    ds
  605.     mov    sp,bp
  606.     pop    bp
  607.     ret
  608.  
  609. _switchsoundtable endp
  610. ;----------------------------------------------------------------------------
  611. ;return the address of the sound table or patchtable
  612. ;return values are in ax
  613. ;values passed are on the stack
  614.  
  615. _getaddr    proc far          ;pass back segment and offset of sound table
  616. public    _getaddr
  617.  
  618.     push    bp
  619.     mov    bp,sp
  620.  
  621.     cmp   word ptr [bp+6],0        ;pass back segment
  622.     jne   getaddr1
  623.     mov   ax,cs
  624.     jmp   short getaddrout
  625.  
  626. getaddr1:
  627.     cmp   word ptr [bp+6],1        ;pass offset of soundtable
  628.     jne   getaddr2
  629.     mov   ax,cs:SoundTablePtr
  630.     jmp   short getaddrout
  631.  
  632. getaddr2:
  633.     cmp   word ptr [bp+6],2        ;pass offset of envelope table
  634.     jne   getaddr3
  635.     mov   ax,cs:SoundTablePtr
  636.  
  637. getaddr3:
  638.     cmp   word ptr [bp+6],3        ;pass address of patchtable
  639.     jne   getaddr4
  640.     mov   ax,offset _Patchtable
  641.  
  642. getaddr4:
  643.     ;cmp   word ptr [bp+6],4        ;pass address of motortable
  644.     ;jne   getaddrout
  645.     ;mov   ax,offset _MotorTable
  646.  
  647. getaddrout:
  648.  
  649.     mov    sp,bp
  650.     pop    bp
  651.     ret
  652.  
  653. _getaddr    endp
  654. ;----------------------------------------------------------------------------
  655. ;initialize sound system variables
  656.  
  657. _initsnd    proc  near
  658.     public    _initsnd
  659.  
  660.     mov    do_sound,0        ;disable sound interrupts
  661.      mov    seed,01234h        ;initialize for random numbers
  662.  
  663.     mov    ax,0120h        ;initialize chip test register to 0
  664.     call    outadlib
  665.     mov    ax,0800h        ;initialize chip to music mode
  666.     call    outadlib
  667.     mov    ax,0bd00h        ;initialize chip to no rhythm
  668.     call    outadlib
  669.  
  670.     mov    motorflag,0        ;no motor
  671.  
  672.     mov    cx,10            ;clear out 9 channels
  673.     mov    bh,0
  674. clear_spram:
  675.     mov    bl,cl
  676.     dec    bl
  677.  
  678.     cmp    bl,9            ;skip conducotr channel
  679.     je    no_conductor
  680.  
  681.     mov    ah,[offset OPOFFSETS+bx] ;get opcode offsets
  682.     add    ah,040h        ;total level reg
  683.     mov    al,03fh        ;max attenuation
  684.     call    outadlib        ;shut it down
  685.     mov    ah,[offset OPOFFSETS+bx] ;get opcode offsets
  686.     add    ah,043h        ;total level reg
  687.     mov    al,03fh        ;max attenuation
  688.     call    outadlib        ;shut it down
  689.  
  690. no_conductor:
  691.     shl    bl,1
  692.     mov    di,[bx+offset schnlPtr]    ;di now has pointer to spram
  693.     call    ClearSpram
  694.     loop    clear_spram
  695.  
  696.     ret
  697.  
  698. _initsnd    endp
  699. ;----------------------------------------------------------------------------
  700. ;main processing loop of sound system
  701. ;*** si points to next byte in sound string
  702. ;*** di points to appropriate sound ram block
  703.  
  704. runsnd     proc  near
  705.  
  706.     cmp    do_sound,0
  707.     jne    go_ahead
  708.     ret
  709.  
  710. go_ahead:
  711.     mov    curchannel,9
  712.  
  713. channellup:            ;RunSound loop
  714.     mov    bl,curchannel
  715.     mov    bh,0
  716.     shl    bl,1
  717.     mov    di,[bx+offset schnlPtr]    ;di now has pointer to sound ram
  718.     mov    al,[di+Duration]        ;check for duration = 0
  719.     or    al,al
  720.     jnz    short still_active
  721.     jmp    not_active
  722.  
  723. still_active:
  724.     mov    bx,offset OPOFFSETS    ;get offset into chip
  725.     add    bl,curchannel
  726.     mov    al,byte ptr [bx]    
  727.     mov    YamOff,al        ;YamOff<-operator offset
  728.  
  729.     cmp    byte ptr [di+autotempo],0
  730.     je    no_auto_tempo
  731.     mov    al,globaltempo
  732.     mov    [di+Tempo],al
  733.  
  734. no_auto_tempo:
  735.     mov    al,[di+TempoCount]    
  736.     add    al,[di+Tempo]        
  737.     mov    [di+TempoCount],al
  738.     jc    short oktempo
  739.     jmp    do_process
  740.  
  741. oktempo:
  742.     dec    byte ptr [di+duration]    ;channel active dec duration
  743.     jz    parse            ;no time left
  744.     mov    al,[di+duration]
  745.     cmp    al,[di+PercentDuration]
  746.     jne    check_gate
  747.     call    noteoff
  748.  
  749. check_gate:
  750.     cmp    al,[di+GateThreshold]
  751.     jne    nottime
  752.     cmp    curchannel,9
  753.     je    nottime
  754.     call    NoteOff
  755. nottime:
  756.     jmp    short do_process        ;still time left
  757.  
  758. parse:
  759.     mov    si,[di+StrPointer]    ;si<-current operand
  760. parse_op:
  761.     lodsw
  762.     or    al,al                       
  763.     jns    note
  764.     jmp    short op_code
  765.  
  766. note:
  767.     call    SetFreq        ;set frequency
  768.     call    NoteOn        ;trigger note
  769.     call    installDuration        ;set up duration
  770.  
  771.     ;*** check velocity stuff
  772.     cmp    word ptr [di+Op1Velocity],0    ;is velocity turned on
  773.     je    checkop2
  774.     jne    short velocityon
  775.  
  776. checkop2:
  777.     cmp    word ptr [di+Op2Velocity],0    ;is velocity turned on
  778.     je    chkNotedur
  779.  
  780. velocityon:
  781.     GETNEXTOP
  782.     mov    [di+Velocity],al
  783.     call    CombineOp2
  784.  
  785.     mov    dx,ADLIBREGS        ;card address for regs
  786.     mov    ah,YamOff        ;get current channel
  787.     add    ah,043h
  788.     call    outadlib
  789.  
  790.     call    CombineOp1
  791.     mov    dx,ADLIBREGS        ;card address for regs
  792.     mov    ah,YamOff        ;get current channel
  793.     add    ah,040h
  794.     call    outadlib
  795. chkNotedur:
  796.     mov    al,installedur
  797.     or    al,al
  798.     je    parse_op
  799.     mov    [di+StrPointer],si    ;for next time
  800.     jmp    short do_process
  801.  
  802. op_code:
  803.     and    al,07Fh        ;get rid of 128 byte offset
  804.     cmp    al,MAXRTN        ;good opcode?
  805.     jle    good_rtn        ;go ahead
  806.     jmp    EOS            ;End activity in channel if bad opcode
  807.  
  808. good_rtn:
  809.     mov    bl,al   
  810.     sub    bh,bh
  811.     shl    bl,1            ;times 2
  812.     mov    bx,[bx+offset opcode_tbl]    ;now bx points to appropriate routine
  813.     jmp    bx            ;dispatch operand to sound routine
  814.  
  815. do_process:
  816.     call    [di+PVector1]
  817.     call    [di+PVector2]
  818.  
  819. not_active:
  820.     dec  curchannel
  821.     js    runsndout
  822.     jmp    channellup
  823.  
  824. runsndout:
  825.     ret
  826.  
  827. runsnd     endp
  828. ;----------------------------------------------------------------------------
  829.  
  830. ;**** opcodes ****
  831. SetLoop:
  832. ;80,number of loops
  833.     mov   [di+lupcounter],ah    ;save loop counter in ram contrl block
  834.     jmp   parse_op        ;go back and parse some more
  835.  
  836. TestLoop:
  837. ;81,label
  838.     dec    byte ptr [di+lupcounter]    ;save loop counter in ram control block
  839.     jnz    branch        ;not zero branch to label
  840.     inc    si            ;point past label address
  841.     jmp    parse_op
  842.  
  843. StartVoice:
  844. ;82,sndtableindex
  845.     push  si
  846.     push  di
  847.     push  bx
  848.  
  849.     mov    bl,ah
  850.     cmp    bl,MAXSOUND2        ;max valid sound code
  851.     jb    snd_code_ok2
  852.     jmp    short sendsndExit2    ;restore registers b4 leaving
  853. snd_code_ok2:
  854.     sub    bh,bh
  855.     shl    bx,1            ;offset into table x2
  856.     add    bx,SoundTablePtr
  857.     mov    si,[bx]        ;si has sound string offset
  858.  
  859.     mov    bx,cs:[si]        ;channel number from string
  860.     mov    al,bh            ;al<-priority
  861.     mov    cl,bl            ;bl = channel number
  862.     sub    bh,bh            ;bh<-0
  863.     shl    bx,1
  864.     mov    di,[bx+offset schnlPtr]    ;of appropriate channel
  865.  
  866.     cmp    al,[di+priority]        ;priority not higher or = ?
  867.     jl    sendsndExit2        ;return
  868.  
  869.     call    ClearSpram
  870.     mov    [di+Priority],al        ;this is the new priority
  871.     inc    si            ;skip over channel and 
  872.     inc    si            ;priority bytes
  873.     mov    [di+StrPointer],si    ;ptr to first data in string
  874.     mov    byte ptr [di+Tempo],0ffh    ;reset tempo
  875.     mov    byte ptr [di+TempoCount],0ffh    ;reset tempo
  876.     mov    byte ptr [di+Duration],01h    ;assure use of first op-code
  877.     mov    do_sound,01
  878.     
  879.     call    clearenv
  880.  
  881. sendsndexit2:
  882.     pop    bx
  883.     pop    di
  884.     pop    si
  885.     jmp    parse_op
  886.  
  887. SetGateThreshold:
  888. ;83,value
  889.     mov    [di+GateThreshold],ah    ;assure use of first op-code
  890.     jmp    parse_op
  891.  
  892. Branch:
  893. ;84,label
  894.     mov    cl,ah
  895.     GETNEXTOP
  896.     xchg    ah,al
  897.     mov    al,cl
  898.     mov    si,ax
  899.     jmp    parse_op
  900.  
  901. CallString:
  902. ;85,label
  903.     dec    si
  904.     mov    bl,[di+StackPointer]        ;grab stack pointer
  905.     mov    bh,0
  906.     shl    bl,1                        ;double for word access
  907.     mov    ax,si                  ;get current address
  908.     inc    ax                          ;jump over subroutine
  909.     inc    ax                          ;address
  910.     mov    [di+Stack0+bx],ax           ;save as return address
  911.     inc    byte ptr [di+StackPointer]    ;bump up stack pointer
  912.     lodsw
  913.     mov    si,ax            ;start at this address
  914.     jmp    parse_op
  915.  
  916. StringReturn:
  917. ;86
  918.     dec    si
  919.     dec    byte ptr [di+StackPointer]    ;point to retrun address
  920.     mov    bl,[di+StackPointer]    ;grab stack pointer
  921.     mov    bh,0
  922.     shl    bl,1            ;double for word access
  923.     mov    ax,[di+Stack0+bx]        ;get return address
  924.     mov    si,ax    ;current address
  925.     jmp    parse_op
  926.  
  927. OctaveOffset:
  928. ;87,octave offset
  929.     mov   [di+OctaveOfst],ah    ;save octave offset in sound ram
  930.     jmp   parse_op
  931.      
  932. EOS: ;end of string
  933. ;88
  934.     mov    byte ptr [di+priority],0
  935.     mov    word ptr [di+StrPointer],0
  936.     cmp    curchannel,9
  937.     je    not_conductor        ;no hardware atatched to channel 9
  938.     call    NoteOff
  939.  
  940. not_conductor:
  941.     jmp   not_active
  942.  
  943. Rest:
  944. ;89,rest length
  945.     call    installDuration
  946.     mov    [di+StrPointer],si    ;for next time
  947.     cmp    curchannel,9
  948.     je    not_conductor2
  949.     call    NoteOff
  950.  
  951. not_conductor2:
  952.     mov    al,installedur
  953.     or    al,al
  954.     je    parse_opj4
  955.     jmp    do_process        ;not_active
  956. parse_opj4:
  957.     jmp    parse_op
  958.  
  959. SetoplReg:
  960. ;8a,register,value
  961.     GETNEXTOP            ;ah has address  al has value
  962.     call    outadlib
  963.     jmp    parse_op
  964.  
  965. newNote:
  966. ;8b,note,length
  967.     xchg    ah,al
  968.     call    SetFreq        ;set frequency
  969.     GETNEXTOP
  970.     xchg    ah,al
  971.     call    installDuration
  972.     mov    [di+StrPointer],si    ;for next time
  973.     mov    al,installedur
  974.     or    al,al
  975.     je    parse_opj3
  976.     jmp    do_process        ;not_active
  977. parse_opj3:
  978.     jmp    parse_op
  979.  
  980. NoteOffset:
  981. ;8c,offset
  982.     mov    [di+NoteOfst],ah
  983.     jmp    parse_op
  984.  
  985. TableModOP:
  986. ;8d,pre8,len8,operator8,tblbase16
  987.     mov    [di+TpTmr],ah        ;
  988.     mov    [di+TpPre],ah        ;
  989.     GETNEXTOP            ;al<-length of table-1
  990.     mov    [di+tmlen],al        ;
  991.     mov    [di+tmoff],al        ;
  992.     GETNEXTOP            ;al<-chip Operator Offset
  993.     mov    [di+TpOp],al        ;
  994.     lodsw
  995.     mov    [di+tmbase],ax
  996.     mov    [di+PVector2],offset TblMod    ;set vector address
  997.     jmp    parse_op
  998.  
  999. StopParse:
  1000. ;8e,channel
  1001.     mov    al,curchannel
  1002.     push    ax
  1003.     push    di
  1004.  
  1005.     mov    bl,ah            ;get addressing to different
  1006.     mov    bh,0            ;sound control block    
  1007.     shl    bl,1
  1008.     mov    di,[bx+offset schnlPtr]    ;di now has pointer to spram
  1009.  
  1010.     mov    byte ptr [di+Duration],0    ;stop channel parsing
  1011.     mov    byte ptr [di+priority],0
  1012.     mov    word ptr [di+StrPointer],0
  1013.  
  1014.     pop    di            ;restore    
  1015.     pop    ax
  1016.     mov    curchannel,al
  1017.     jmp   parse_op
  1018.  
  1019. StuffPatch:
  1020. ;90,patchindex
  1021.     push    si
  1022.     mov    cl,YamOff
  1023.  
  1024.     sub    bx,bx
  1025.     mov    bl,ah
  1026.     shl    bx,1            ;for patches > 127  ddt 3/18
  1027.     mov    si,[bx+offset _Patchtable]
  1028.     call    writepatch
  1029.     pop    si
  1030.     jmp    parse_op        ;go back and parse some more
  1031.  
  1032. PitchDelta:
  1033. ;91,pre,hidelt,lodelt
  1034.     mov    [di+Pdeltpre],ah        ;save it (0 means pdelt off)
  1035.     GETNEXTOP            ;get high byte of delta
  1036.     xchg    ah,al            ;put'em in there places
  1037.     GETNEXTOP            ;get low byte of delta
  1038.     mov    [di+Pdelt],ax        ;save it
  1039.     mov    [di+PVector1],offset DoPitchDelta    ;set vector address
  1040.     mov    [di+Pdeltcount],byte ptr 0ffh
  1041.     jmp    parse_op
  1042.  
  1043. ClearPitchDelta:
  1044. ;92
  1045.     dec    si
  1046.     mov    [di+PVector1],offset NullVector    ;set vector address
  1047.     mov    word ptr [di+Pdelt],0        ;save it
  1048.     jmp   parse_op
  1049.  
  1050. FracPitch:
  1051. ;93,byte
  1052.     mov    [di+FracPitchLow],ah    ;save it 
  1053.     jmp   parse_op
  1054.  
  1055. Vibrato:
  1056. ;95,prescaler,shift,count,delay
  1057.     mov    [di+Vibpre],ah        ;save it (0 means vib off)
  1058.     GETNEXTOP            ;get shift count
  1059.     mov    [di+Vibshift],al        ;save it
  1060.     GETNEXTOP            ;get excursion count value
  1061.     mov    [di+VibNewCount],al    ;save it
  1062.     inc    byte ptr [di+VibNewCount]    ;make up for first time decrement
  1063.     shl    al,1            ;half vibcount
  1064.     mov    [di+Vibcount],al        ;save it
  1065.     GETNEXTOP            ;get delay
  1066.     mov    [di+Vibdelay],al        ;save it
  1067.     mov    [di+PVector1],offset DoVibrato
  1068.     jmp    parse_op
  1069.  
  1070. SetPriority:
  1071. ;9a,priority
  1072.     mov    [di+priority],ah
  1073.     jmp   parse_op
  1074.  
  1075. InitSync:
  1076. ;9c,sync value
  1077.     shr    ah,1
  1078.     mov    notesync,ah
  1079.     mov    notecntr,ah
  1080.     mov    presync,0ffh
  1081.     mov    ah,0
  1082.     mov    syncbyte,ah
  1083.     mov    synchi,ah
  1084.     jmp    parse_op
  1085.  
  1086. WaitSync:
  1087. ;9d
  1088.     mov    al,synchi
  1089.     or    al,al
  1090.     jne    lookingforhilo
  1091.  
  1092.     and    ah,syncbyte
  1093.     jne    notsyncedyet
  1094.     inc    synchi
  1095.     jmp    short notsyncedyet
  1096.  
  1097. lookingforhilo:
  1098.     and    ah,syncbyte
  1099.     je    notsyncedyet
  1100.     mov    synchi,0
  1101.     jmp    parse_op
  1102.  
  1103. notsyncedyet:
  1104.     dec    si
  1105.     dec    si
  1106.     mov    byte ptr [di+Duration],1
  1107.     mov    [di+StrPointer],si    ;save string pointer
  1108.     jmp    not_active        ;parse next channel
  1109.  
  1110. start_channel:
  1111.     jmp    parse_op
  1112.  
  1113. SetAccentAttn:
  1114. ;9e,attenuation
  1115.     mov    [di+accentattn],ah    ;save it 
  1116.     call    CombineAttn        ;combine and stuff now
  1117.     jmp    parse_op
  1118.  
  1119. Stay:
  1120. ;a0,duration
  1121.     call    installDuration
  1122.     mov    [di+StrPointer],si    ;for next time
  1123.     mov    al,installedur
  1124.     or    al,al
  1125.     je    parse_opj2
  1126.     jmp    do_process        ;not_active
  1127. parse_opj2:
  1128.     jmp    parse_op
  1129.  
  1130. ReTrigger:
  1131. ;a1,duration
  1132.     call    installDuration
  1133.     call    NoteOn
  1134.     mov    [di+StrPointer],si    ;for next time
  1135.     mov    al,installedur
  1136.     or    al,al
  1137.     je    parse_opj1
  1138.     jmp    do_process
  1139. parse_opj1:
  1140.     jmp    parse_op
  1141.  
  1142. NotePercent:
  1143. ;a4,percent
  1144.     and    ah,007h
  1145.     mov    [di+NotePercentVal],ah    ;save it 
  1146.     jmp    parse_op
  1147.     
  1148. SetMusicTempo:
  1149. ;a6,globalTempo
  1150.     mov    globalTempo,ah
  1151.     jmp    parse_op
  1152.  
  1153. KillVector2:
  1154. ;a7
  1155.     dec    si
  1156.     mov    [di+PVector2],offset NullVector    ;set process vector
  1157.     jmp    parse_op
  1158.  
  1159. SetTempo:
  1160. ;a9,tempo
  1161.     mov    [di+Tempo],ah        ;save tempo in global variable
  1162.     jmp    parse_op
  1163.  
  1164. SetChannelAttn:
  1165. ;ab,attn
  1166.     mov    [di+channelattn],ah    ;save it 
  1167.     jmp   parse_op
  1168.  
  1169. SetsysAttn:
  1170. ;ac,channel,attn
  1171.     mov    al,curchannel
  1172.     push    ax
  1173.     push    di
  1174.  
  1175.     GETNEXTOP            ;get attenuation
  1176.     mov    curchannel,ah        ;reset cureent channel temporarily
  1177.     mov    bl,ah            ;get addressing to different
  1178.     mov    bh,0            ;sound control block    
  1179.     shl    bl,1
  1180.     mov    di,[bx+offset schnlPtr]    ;di now has pointer to spram
  1181.     mov    [di+sysAttn],al        ;save it 
  1182.     call    CombineAttn        ;combine and stuff now
  1183.  
  1184.     pop    di            ;restore    
  1185.     pop    ax
  1186.     mov    curchannel,al
  1187.     jmp   parse_op
  1188.  
  1189. SetsysAttnDelta:
  1190. ;ad,channel,delta
  1191.     mov    al,curchannel
  1192.     push    ax
  1193.     push    di
  1194.  
  1195.     mov    curchannel,ah        ;reset curent channel temporarily
  1196.     sub    bx,bx
  1197.     mov    bl,ah            ;get addressing to different
  1198.     GETNEXTOP            ;al<-attenuation
  1199.     shl    bl,1
  1200.     mov    di,[bx+offset schnlPtr]    ;di now has pointer to spram
  1201.     add    al,byte ptr [di+sysAttn]    ;add delta to current attenuation
  1202.     mov    [di+sysAttn],al        ;save it 
  1203.     call    CombineAttn        ;combine and stuff now
  1204.  
  1205.     pop    di            ;restore    
  1206.     pop    ax
  1207.     mov    curchannel,al
  1208.     jmp   parse_op
  1209.  
  1210. SetAmDepth:
  1211. ;ae,depth
  1212.     and    ah,01
  1213.     mov    cl,7
  1214.     shl    ah,cl
  1215.     mov    bl,ShadowBD
  1216.     and    bl,07fh
  1217.     or    bl,ah
  1218.     mov    ShadowBD,bl
  1219.     mov    ah,0bdh
  1220.     mov    al,bl
  1221.     call    outadlib
  1222.     jmp    parse_op
  1223.  
  1224. SetVibDepth:
  1225. ;af,depth
  1226.     and    ah,01
  1227.     mov    cl,6
  1228.     shl    ah,cl
  1229.     mov    bl,ShadowBD
  1230.     and    bl,0bfh
  1231.     or    bl,ah
  1232.     mov    ShadowBD,bl
  1233.     mov    ah,0bdh
  1234.     mov    al,bl
  1235.     call    outadlib
  1236.     jmp    parse_op
  1237.  
  1238. SetSignedAttn:
  1239. ;b0,signedAccentDelta
  1240.     add    ah,[di+AccentAttn]
  1241.     mov    [di+AccentAttn],ah    ;save it 
  1242.     call    CombineAttn        ;combine and stuff now
  1243.     jmp   parse_op
  1244.  
  1245. KillChannel:
  1246. ;b3,channel
  1247.     mov    al,curchannel
  1248.     push    ax
  1249.     push    di
  1250.  
  1251.     cmp    ah,0
  1252.     jne    not_motor_channel
  1253.     mov    motorflag,0
  1254.  
  1255. not_motor_channel:
  1256.     mov    curchannel,ah
  1257.     mov    bl,ah            ;get addressing to different
  1258.     mov    bh,0            ;sound control block    
  1259.     shl    bl,1
  1260.     mov    di,[bx+offset schnlPtr]    ;di now has pointer to spram
  1261.  
  1262.     mov    byte ptr [di+Duration],0    ;stop channel parsing
  1263.     mov    byte ptr [di+priority],0
  1264.     mov    word ptr [di+StrPointer],0
  1265.  
  1266.     mov    byte ptr [di+sysAttn],0    ;clear system atten when channel is killed
  1267.     cmp    curchannel,9        ;are we in conductor channel?
  1268.     je    short KillDone
  1269.  
  1270.     mov    bl,ah            ;get offset into chip
  1271.     xor    bh,bh
  1272.     mov    cl,[bx+offset OPOFFSETS]
  1273.  
  1274.     mov    ah,0c0h        ;fb/alg register
  1275.     add    ah,curchannel        ;proper slot
  1276.     mov    al,0            ;set for stack
  1277.     call    outadlib
  1278.  
  1279.     mov    ah,043h
  1280.     add    ah,cl            ;total level/carrier
  1281.     mov    al,03fh        ;max attenuation
  1282.     call    outadlib
  1283.  
  1284.     mov    ah,083h
  1285.     add    ah,cl            ;sustain release
  1286.     mov    al,0ffh        ;min release time
  1287.     call    outadlib
  1288.  
  1289.     mov    ah,0b0h        ;kon block
  1290.     add    ah,curchannel
  1291.     mov    al,0            ;key off
  1292.     call    outadlib
  1293.  
  1294. KillDone:
  1295.     pop    di            ;restore    
  1296.     pop    ax
  1297.     mov    curchannel,al
  1298.     jmp    parse_op
  1299.  
  1300. RandomPitch:
  1301. ;b5,wordmask
  1302.     GETNEXTOP
  1303.     mov    bx,ax
  1304.     call    Random        ;ax<-16 pseudo-random number
  1305.     and    ax,bx            ;ax<-anded offset
  1306.     mov    cl,byte ptr[di+block]    ;cl<-gate/block/hiFreq
  1307.     mov    bh,cl            ;bh<-gate/block/hiFreq
  1308.     and    cl,020h        ;cl<-isolated gate information
  1309.     mov    bl,[di+FreqLow]
  1310.     and    bh,01FH        ;bh<-isolated block/HiFreq
  1311.     add    bx,ax            ;bx<-+=Randomed frequency
  1312.     or    bh,cl            ;bh<-|=gate infomation
  1313.  
  1314.     mov    ah,0a0h        ;al<-chip Frequency Low base
  1315.     add    ah,curchannel
  1316.     mov    al,bl
  1317.     call    outadlib
  1318.  
  1319.     mov    ah,0b0h        ;al<-chip Frequency Low base
  1320.     add    ah,curchannel
  1321.     mov    al,bh
  1322.     call    outadlib
  1323.     jmp    parse_op
  1324.  
  1325. KillVector1:
  1326. ;b6
  1327.     dec    si
  1328.     mov    [di+PVector1],offset NullVector    ;set process vector
  1329.     jmp    parse_op
  1330.  
  1331. SetPitchBend:
  1332. ;b9
  1333.     mov    [di+BendValue],ah
  1334.     mov    al,[di+noteval]
  1335.     push    ax
  1336.     mov    ch,al            ;note in ch
  1337.  
  1338.     and    ch,0f0h        ;and off note value
  1339.     mov    bl,[di+OctaveOfst]    ;get octave offset
  1340.     add    ch,bl            ;add em'
  1341.  
  1342.     and    al,0fh        ;get rid of octave info
  1343.     mov    bl,[di+NoteOfst]        ;get note offset
  1344.     add    al,bl            ;add note offset
  1345.  
  1346.     cmp    al,0ch        ;did it wrap to next octave?
  1347.     jge    upanoctave2
  1348.     cmp    al,0
  1349.     jge    sameoctave2
  1350.     add    al,0ch
  1351.     sub    ch,10h        ;add one octave
  1352.     jmp    short sameoctave2
  1353.  
  1354. upanoctave2:
  1355.     sub    al,0ch
  1356.     add    ch,10h        ;add one octave
  1357.  
  1358. sameoctave2:
  1359.     mov    bl,al
  1360.     mov    bh,0
  1361.     shl    bl,1
  1362.     mov    ax,[bx+offset FreqTable]     ;get freq
  1363.     sub    dx,dx
  1364.     mov    dl,byte ptr [di+FracPitchLow]
  1365.     add    ax,dx            ;ax<-+=8 bits of Pitch Offset
  1366.     shr    ch,1
  1367.     shr    ch,1
  1368.     and    ch,01ch
  1369.     or    ch,ah            ;combine high two bits of freq
  1370.     mov    cl,al
  1371.  
  1372.     cmp    byte ptr [di+BendValue],0      ;bend value in ah
  1373.     jl    bend_down
  1374.  
  1375.     xor    bh,bh
  1376.     mov    bl,[di+noteval]        ;bl gets note
  1377.     and    bl,0fh
  1378.     inc    bl
  1379.     inc    bl
  1380.     shl    bx,1            ;double for table index
  1381.     push    si
  1382.     mov    si,[bx+offset pbendtable]    ;index into table
  1383.  
  1384.     xor    bh,bh
  1385.     mov    bl,[di+BendValue]        ;bend value in ah
  1386.     mov    al,[si+bx]        ;get bend value
  1387.     pop    si
  1388.     xor    ah,ah            ;clear ah
  1389.     add    cx,ax            ;combine bend and em
  1390.     jmp    short stuff_bend
  1391.  
  1392. bend_down:
  1393.     xor    bh,bh
  1394.     mov    bl,[di+noteval]        ;bl gets note
  1395.     and    bl,0fh
  1396.     shl    bx,1            ;double for table index
  1397.     push    si
  1398.     mov    si,[bx+offset pbendtable]    ;index into table
  1399.  
  1400.     xor    bh,bh
  1401.     mov    bl,[di+BendValue]        ;bend value in ah
  1402.     xor    bl,0ffh
  1403.     inc    bl
  1404.     mov    al,[si+bx]        ;get bend value
  1405.     pop    si
  1406.     xor    ah,ah            ;clear ah
  1407.     sub    cx,ax            ;combine bend and em
  1408.     jmp    short stuff_bend
  1409.  
  1410. stuff_bend:
  1411.     mov    ah,0a0h        
  1412.     mov    al,[di+Block]
  1413.     and    al,020h        ;isolate trigger state
  1414.     or    ch,al            ;combine trigger and freq info
  1415.     mov    [di+Block],ch        ;ch has block / freq high
  1416.     mov    [di+FreqLow],cl        ;cl has freqlow
  1417.  
  1418.     mov    ah,0a0h        ;base of frequency low reg
  1419.     add    ah,curchannel        ;add channel offset
  1420.     mov    al,cl
  1421.     call    outadlib
  1422.  
  1423.     mov    ah,0b0h        ;base of frequency high/block reg
  1424.     add    ah,curchannel        ;add channel offset
  1425.     mov    al,ch            ;freq high block data
  1426.     call    outadlib
  1427.     pop    ax
  1428.     jmp    parse_op
  1429.  
  1430. getmusicTempo:
  1431. ;ba
  1432.     dec    si
  1433.     mov    al,globalTempo
  1434.     mov    byte ptr [di+Tempo],al
  1435.     jmp    parse_op
  1436.  
  1437. SNOP:
  1438. ;bb
  1439.     dec    si
  1440.     jmp    parse_op
  1441.  
  1442. RandomDuration:
  1443. ;bc,andmask
  1444.     mov    [di+RndDurMask],ah
  1445.     jmp    parse_op
  1446.  
  1447. tempodelta:
  1448. ;bd,signedtempo
  1449. ;if signedtempo is + and result overflows   tempo<-0xff
  1450. ;if signedtempo is - and result underflows  tempo<-1
  1451.  
  1452.     or    ah,ah
  1453.     js    tgoindown
  1454.     add    ah,[di+tempo]        ;tempo+=tempodelta
  1455.     jnc    tempodeltaok        ;if no overflow stuff
  1456.     mov    ah,0ffh        ;else limit to 0xff
  1457.     jmp    short    tempodeltaok
  1458. tgoindown:
  1459.     add    ah,[di+tempo]
  1460.     cmp    ah,[di+tempo]
  1461.     jb    tempodeltaok
  1462.     mov    ah,1
  1463. tempodeltaok:
  1464.     mov    [di+tempo],ah
  1465.     jmp    parse_op
  1466.  
  1467. MotorOn:
  1468. ;bf,flag,table number
  1469.  
  1470. check1:
  1471.  
  1472. MotorOff:
  1473. ;c0
  1474.  
  1475. DrumSetup:
  1476. ;c1,patch1,patch2,patch3,freq1 h,freq1 l,freq2 h,freq2 l,freq3 h,freq3 l
  1477.     mov    al,curchannel        ;save current channel
  1478.     push    ax
  1479.     mov    al,YamOff        ;save current ofset intoe chip
  1480.     push    ax
  1481.     push    si
  1482.  
  1483.     mov    curchannel,6
  1484.     mov    bx,offset OPOFFSETS    ;get offset into chip
  1485.     add    bl,6
  1486.     mov    al,byte ptr [bx]    
  1487.     mov    YamOff,al        ;YamOff<-operator offset
  1488.     mov    dx,ADLIBREGS
  1489.     mov    cl,YamOff
  1490.     sub    bx,bx
  1491.     mov    bl,ah
  1492.     shl    bx,1
  1493.     mov    si,[bx+offset _Patchtable]
  1494.     mov    al,[si+6]
  1495.     mov    KickShadow,al
  1496.     call    writepatch        ;first patch kick drum
  1497.  
  1498.     pop    si
  1499.     GETNEXTOP            ;second patch index
  1500.     push    si
  1501.     mov    curchannel,7
  1502.     mov    bx,offset OPOFFSETS    ;get offset into chip
  1503.     add    bl,7
  1504.     mov    ah,byte ptr [bx]    
  1505.     mov    YamOff,ah        ;YamOff<-operator offset
  1506.     mov    dx,ADLIBREGS
  1507.     mov    cl,YamOff
  1508.     sub    bx,bx
  1509.     mov    bl,al
  1510.     shl    bx,1
  1511.     mov    si,[bx+offset _Patchtable]
  1512.     mov    al,[si+5]
  1513.     mov    HihatShadow,al
  1514.     mov    al,[si+6]
  1515.     mov    SnareShadow,al
  1516.     call    writepatch        ;second patch snare and hihat
  1517.  
  1518.     pop    si
  1519.     GETNEXTOP            ;third patch index
  1520.     push    si
  1521.     mov    curchannel,8
  1522.     mov    bx,offset OPOFFSETS    ;get offset into chip
  1523.     add    bl,8
  1524.     mov    ah,byte ptr [bx]    
  1525.     mov    YamOff,ah        ;YamOff<-operator offset
  1526.     mov    dx,ADLIBREGS
  1527.     mov    cl,YamOff
  1528.     sub    bx,bx
  1529.     mov    bl,al
  1530.     shl    bx,1
  1531.     mov    si,[bx+offset _Patchtable]
  1532.     mov    al,[si+5]
  1533.     mov    TomShadow,al
  1534.     mov    al,[si+6]
  1535.     mov    RideShadow,al
  1536.     call    writepatch        ;third patch tom and ride
  1537.     
  1538.     pop    si
  1539.  
  1540.     GETNEXTOP            ;get freq 1 high
  1541.     and    al,02fh        ;and off kon
  1542.     mov    spram7+BLOCK,al
  1543.     mov    ah,0b6h
  1544.     call    outadlib    
  1545.  
  1546.     GETNEXTOP            ;get freq 1 low
  1547.     mov    ah,0a6h
  1548.     call    outadlib    
  1549.  
  1550.     GETNEXTOP            ;get freq 2 high
  1551.     and    al,02fh        ;and off kon
  1552.     mov    spram8+BLOCK,al
  1553.     mov    ah,0b7h
  1554.     call    outadlib    
  1555.  
  1556.     GETNEXTOP            ;get freq 2 low
  1557.     mov    ah,0a7h
  1558.     call    outadlib    
  1559.  
  1560.     GETNEXTOP            ;get freq 3 high
  1561.     and    al,02fh        ;and off kon
  1562.     mov    spram9+BLOCK,al
  1563.     mov    ah,0b8h
  1564.     call    outadlib    
  1565.  
  1566.     GETNEXTOP            ;get freq 3 low
  1567.     mov    ah,0a8h
  1568.     call    outadlib    
  1569.  
  1570.     mov    drummask,020h
  1571.  
  1572.     pop    ax            ;restore chip offset
  1573.     mov    YamOff,al
  1574.     pop    ax            ;restore current channel
  1575.     mov    curchannel,al
  1576.     jmp    parse_op
  1577.  
  1578. DoDrum:
  1579. ;c2,mask,duration  trigger drum
  1580. ;0x01-hihat  0x02-ride  0x04-tom  0x08-snare 0x10-bass drum
  1581.  
  1582.     mov    dx,ADLIBREGS
  1583.     mov    al,0bdh
  1584.     out    dx,al
  1585.     call    Wait33
  1586.     inc    dx
  1587.     xchg    ah,al
  1588.     push    ax
  1589.     and    al,01fh
  1590.     xor    al,0ffh        ;invert mask
  1591.     and    al,drummask
  1592.     or    al,020h        ;drum mode bit
  1593.     out    dx,al            ;send to card
  1594.     call    Wait34
  1595.  
  1596.     pop    ax
  1597.     or    al,DrumMask
  1598.     mov    DrumMask,al
  1599.     or    al,ShadowBD        ;now turn'em on
  1600.     or    al,020h        ;drum mode bit
  1601.  
  1602.     out    dx,al            ;send to card
  1603.     call    Wait34
  1604.     jmp    parse_op
  1605.  
  1606. DrumOff:    
  1607. ;c3  no args   turn off drum mode
  1608.     dec    si
  1609.     mov    al,ShadowBD
  1610.     mov    DrumMask,0
  1611.     and    al,0c0h
  1612.     mov    ah,0bdh
  1613.     call    outadlib
  1614.     jmp    parse_op
  1615.  
  1616. DrumAttn:
  1617. ;c4,mask,attn
  1618.     GETNEXTOP
  1619.     mov    bx,ax        ;save operands (ax needed for outadlib)
  1620.  
  1621.     test    ah,001h    ;check hihat
  1622.     jz    check_ride
  1623.     mov    HihatAttn,al
  1624.     xor    ah,ah
  1625.     add    al,HihatShadow
  1626.     add    al,HihatMaster
  1627.     add    al,HihatAttn
  1628.     call    CheckWrap
  1629.     mov    ah,051h
  1630.     call    outadlib
  1631.  
  1632. check_ride:
  1633.     mov    ax,bx
  1634.     test    ah,002h    ;check ride
  1635.     jz    check_tom
  1636.     mov    RideAttn,al
  1637.     xor    ah,ah
  1638.     add    al,RideShadow
  1639.     add    al,RideMaster
  1640.     add    al,RideAttn
  1641.     call    CheckWrap
  1642.     mov    ah,055h
  1643.     call    outadlib
  1644.  
  1645. check_tom:
  1646.     mov    ax,bx
  1647.     test    ah,004h    ;check tom
  1648.     jz    check_snare
  1649.     mov    TomAttn,al
  1650.     xor    ah,ah
  1651.     add    al,TomShadow
  1652.     add    al,TomMaster
  1653.     add    al,TomAttn
  1654.     call    CheckWrap
  1655.     mov    ah,052h
  1656.     call    outadlib
  1657.  
  1658. check_snare:
  1659.     mov    ax,bx
  1660.     test    ah,008h    ;check snare
  1661.     jz    check_kick
  1662.     mov    SnareAttn,al
  1663.     xor    ah,ah
  1664.     add    al,SnareShadow
  1665.     add    al,SnareMaster
  1666.     add    al,SnareAttn
  1667.     call    CheckWrap
  1668.     mov    ah,054h
  1669.     call    outadlib
  1670.  
  1671. check_kick:
  1672.     mov    ax,bx
  1673.     test    ah,010h    ;check kick
  1674.     jz    drum_attn_done
  1675.     mov    KickAttn,al
  1676.     xor    ah,ah
  1677.     add    al,KickShadow
  1678.     add    al,KickMaster
  1679.     add    al,KickAttn
  1680.     call    CheckWrap
  1681.     mov    ah,053h
  1682.     call    outadlib
  1683.  
  1684. drum_attn_done:
  1685.     jmp    parse_op
  1686.  
  1687. DrumFade:
  1688. ;c5,mask,attn amount
  1689.     GETNEXTOP
  1690.     mov    bx,ax        ;save operands (ax needed for outadlib)
  1691.  
  1692.     test    ah,001h    ;check hihat
  1693.     jz    check_ride2
  1694.     xor    ah,ah
  1695.     add    al,HihatShadow
  1696.     add    al,HihatMaster
  1697.     add    al,HihatAttn
  1698.     call    checkwrap
  1699.     mov    HihatMaster,al
  1700.     mov    ah,051h
  1701.     call    outadlib
  1702.  
  1703. check_ride2:
  1704.     mov    ax,bx
  1705.     test    ah,002h    ;check ride
  1706.     jz    check_tom2
  1707.     xor    ah,ah
  1708.     add    al,RideShadow
  1709.     add    al,RideMaster
  1710.     add    al,RideAttn
  1711.     call    checkwrap
  1712.     mov    RideMaster,al
  1713.     mov    ah,055h
  1714.     call    outadlib
  1715.  
  1716. check_tom2:
  1717.     mov    ax,bx
  1718.     test    ah,004h    ;check tom
  1719.     jz    check_snare2
  1720.     xor    ah,ah
  1721.     add    al,TomShadow
  1722.     add    al,TomMaster
  1723.     add    al,TomAttn
  1724.     call    checkwrap
  1725.     mov    TomMaster,al
  1726.     mov    ah,052h
  1727.     call    outadlib
  1728.  
  1729. check_snare2:
  1730.     mov    ax,bx
  1731.     test    ah,008h    ;check snare
  1732.     jz    check_kick2
  1733.     xor    ah,ah
  1734.     add    al,SnareShadow
  1735.     add    al,SnareMaster
  1736.     add    al,SnareAttn
  1737.     call    checkwrap
  1738.     mov    SnareMaster,al
  1739.     mov    ah,054h
  1740.     call    outadlib
  1741.  
  1742. check_kick2:
  1743.     mov    ax,bx
  1744.     test    ah,010h    ;check kick
  1745.     jz    drum_attn_done2
  1746.     xor    ah,ah
  1747.     add    al,KickShadow
  1748.     add    al,KickMaster
  1749.     add    al,KickAttn
  1750.     call    checkwrap
  1751.     mov    KickMaster,al
  1752.     mov    ah,053h
  1753.     call    outadlib
  1754.  
  1755. drum_attn_done2:
  1756.     jmp    parse_op
  1757.  
  1758. DrumMasterAttn:
  1759. ;c6,mask,attn amount
  1760.     GETNEXTOP
  1761.     mov    bx,ax        ;save operands (ax needed for outadlib)
  1762.  
  1763.     test    ah,001h    ;check hihat
  1764.     jz    check_ride3
  1765.     mov    HihatMaster,al
  1766.     xor    ah,ah
  1767.     add    al,HihatShadow
  1768.     add    al,HihatAttn
  1769.     call    checkwrap
  1770.     mov    ah,051h
  1771.     call    outadlib
  1772.  
  1773. check_ride3:
  1774.     mov    ax,bx
  1775.     test    ah,002h    ;check ride
  1776.     jz    check_tom3
  1777.     mov    RideMaster,al
  1778.     xor    ah,ah
  1779.     add    al,RideShadow
  1780.     add    al,RideAttn
  1781.     call    checkwrap
  1782.     mov    ah,055h
  1783.     call    outadlib
  1784.  
  1785. check_tom3:
  1786.     mov    ax,bx
  1787.     test    ah,004h    ;check tom
  1788.     jz    check_snare3
  1789.     mov    TomMaster,al
  1790.     xor    ah,ah
  1791.     add    al,TomShadow
  1792.     add    al,TomAttn
  1793.     call    checkwrap
  1794.     mov    ah,052h
  1795.     call    outadlib
  1796.  
  1797. check_snare3:
  1798.     mov    ax,bx
  1799.     test    ah,008h    ;check snare
  1800.     jz    check_kick3
  1801.     mov    SnareMaster,al
  1802.     xor    ah,ah
  1803.     add    al,SnareShadow
  1804.     add    al,SnareAttn
  1805.     call    checkwrap
  1806.     mov    ah,054h
  1807.     call    outadlib
  1808.  
  1809. check_kick3:
  1810.     mov    ax,bx
  1811.     test    ah,010h    ;check kick
  1812.     jz    drum_attn_done3
  1813.     mov    KickMaster,al
  1814.     xor    ah,ah
  1815.     add    al,KickShadow
  1816.     add    al,KickAttn
  1817.     call    checkwrap
  1818.     mov    ah,053h
  1819.     call    outadlib
  1820.  
  1821. drum_attn_done3:
  1822.     jmp    parse_op
  1823.  
  1824. SetAutoTempo:
  1825. ;c8,flag  zero off no-zero on
  1826.     mov    [di+autotempo],ah        ;store flag value
  1827.     jmp   parse_op
  1828.  
  1829. SetVelocity:
  1830. ;c9,op 1 shift count, op 2 shift count
  1831.     mov    [di+Op1Velocity],ah    ;save it 
  1832.     GETNEXTOP            ;get op2 vel shift 
  1833.     mov    [di+Op2Velocity],al    ;save it 
  1834.     jmp   parse_op
  1835.  
  1836. ;----------------------------------------------------------------------------
  1837. ;set frequency of sound chip to a note
  1838. ;note value is in al
  1839.  
  1840. SetFreq    proc            ;al has note update hardware/shadow
  1841. public  SetFreq
  1842.  
  1843.     push    ax
  1844.     mov    [di+noteval],al
  1845.     mov    ch,al            ;note in ch
  1846.  
  1847.     and    ch,0f0h        ;and off note value
  1848.     mov    bl,[di+OctaveOfst]    ;get octave offset
  1849.     add    ch,bl            ;add em'
  1850.  
  1851.     and    al,0fh        ;get rid of octave info
  1852.     mov    bl,[di+NoteOfst]        ;get note offset
  1853.     add    al,bl            ;add note offset
  1854.  
  1855.     cmp    al,0ch        ;did it wrap to next octave?
  1856.     jge    upanoctave
  1857.     cmp    al,0
  1858.     jge    sameoctave
  1859.     add    al,0ch
  1860.     sub    ch,10h        ;add one octave
  1861.     jmp    short sameoctave
  1862.  
  1863. upanoctave:
  1864.     sub    al,0ch
  1865.     add    ch,10h        ;add one octave
  1866.  
  1867. sameoctave:
  1868.     mov    bl,al
  1869.     mov    bh,0
  1870.     shl    bl,1
  1871.     mov    ax,[bx+offset FreqTable]     ;get freq
  1872.     sub    dx,dx
  1873.     mov    dl,byte ptr [di+FracPitchLow]
  1874.     add    ax,dx            ;ax<-+=8 bits of Pitch Offset
  1875.     shr    ch,1
  1876.     shr    ch,1
  1877.     and    ch,01ch
  1878.     or    ch,ah            ;combine high two bits of freq
  1879.     mov    cl,al
  1880.  
  1881.  
  1882.     cmp    byte ptr [di+BendValue],0      ;bend value in ah
  1883.     je    no_pitchbend
  1884.     jl    bend_down2
  1885.  
  1886.     xor    bh,bh
  1887.     mov    bl,[di+noteval]        ;bl gets note
  1888.     and    bl,0fh
  1889.     inc    bl
  1890.     inc    bl
  1891.     shl    bx,1            ;double for table index
  1892.     push    si
  1893.     mov    si,[bx+offset pbendtable]    ;index into table
  1894.  
  1895.     xor    bh,bh
  1896.     mov    bl,[di+BendValue]        ;bend value in ah
  1897.     mov    al,[si+bx]        ;get bend value
  1898.     pop    si
  1899.     xor    ah,ah            ;clear ah
  1900.     add    cx,ax            ;combine bend and em
  1901.     jmp    short no_pitchbend
  1902.  
  1903. bend_down2:
  1904.     xor    bh,bh
  1905.     mov    bl,[di+noteval]        ;bl gets note
  1906.     and    bl,0fh
  1907.     shl    bx,1            ;double for table index
  1908.     push    si
  1909.     mov    si,[bx+offset pbendtable]    ;index into table
  1910.  
  1911.     xor    bh,bh
  1912.     mov    bl,[di+BendValue]        ;bend value in ah
  1913.     xor    bl,0ffh
  1914.     inc    bl
  1915.     mov    al,[si+bx]        ;get bend value
  1916.     pop    si
  1917.     xor    ah,ah            ;clear ah
  1918.     sub    cx,ax            ;combine bend and em
  1919.  
  1920. no_pitchbend:
  1921.     mov    ah,0a0h        
  1922.     mov    al,[di+Block]
  1923.     and    al,020h        ;isolate trigger state
  1924.     or    ch,al            ;combine trigger and freq info
  1925.     mov    [di+Block],ch        ;ch has block / freq high
  1926.     mov    [di+FreqLow],cl        ;cl has freqlow
  1927.  
  1928.     mov    ah,0a0h        ;base of frequency low reg
  1929.     add    ah,curchannel        ;add channel offset
  1930.     mov    al,cl
  1931.     call    outadlib
  1932.  
  1933.     mov    ah,0b0h        ;base of frequency high/block reg
  1934.     add    ah,curchannel        ;add channel offset
  1935.     mov    al,ch            ;freq high block data
  1936.     call    outadlib
  1937.     pop    ax
  1938.     ret
  1939.  
  1940. SetFreq    endp
  1941. ;----------------------------------------------------------------------------
  1942. ;trigger note on 
  1943.  
  1944. NoteOn    proc            ;trigger chip note on
  1945. public  NoteOn
  1946.     push    ax
  1947.     mov    ah,0b0h        ;sustain / release
  1948.     add    ah,curchannel        ;curchannel is offset into regs
  1949.  
  1950.     mov    al,[di+Block]
  1951.     or    al,020h        ;set bit to one
  1952.     mov    [di+Block],al        ;update block shadow    
  1953.     call    outadlib
  1954.  
  1955.     mov    cl,[di+VibShift]        ;vibrato stuff
  1956.     mov    al,9
  1957.     sub    al,cl
  1958.     mov    cl,al
  1959.     mov    ax,[di+FreqLow]
  1960.     and    ax,03ffh
  1961.     shr    ax,cl
  1962.     mov    ah,0
  1963.     mov    [di+VibStep],ax
  1964.  
  1965.     mov    cl,[di+VibDelay]        ;vibrato stuff
  1966.     mov    [di+VibDelayCount],cl    ;vibrato stuff
  1967.     pop    ax
  1968.     ret
  1969.  
  1970. NoteOn    endp
  1971. ;----------------------------------------------------------------------------
  1972. ;turn note off (start release segment)
  1973.  
  1974. NoteOff    proc            ;trigger chip note off
  1975. public  NoteOff
  1976.  
  1977.     cmp    drummask,0        ;5/30/90
  1978.     je    no_drumsNO        ;5/30/90
  1979.     cmp    curchannel,6        ;5/30/90
  1980.     jl    no_drumsNO        ;5/30/90
  1981.     ret
  1982. no_drumsNO:
  1983.     cmp    curchannel,9
  1984.     je    noteoffexit
  1985.     mov    ah,0b0h        ;sustain / release
  1986.     add    ah,curchannel
  1987.     mov    al,[di+Block]
  1988.     and    al,0dfh        ;set bit to zero
  1989.     mov    [di+Block],al        ;update block shadow
  1990.     call    outadlib
  1991.  
  1992. noteoffexit:
  1993.     ret
  1994.  
  1995. NoteOff    endp
  1996. ;----------------------------------------------------------------------------
  1997. ;note duration processing
  1998. ;ah has duration
  1999.  
  2000. InstallDuration    proc
  2001.     mov    installedur,ah
  2002.     cmp    byte ptr [di+RndDurMask],0
  2003.     mov    bl,ah
  2004.     je    short    noRandomDur
  2005.     call    Random
  2006.     and    al,[di+RndDurMask]
  2007.     add    bl,al
  2008.     mov    [di+Duration],bl        ;save duration in ram control block
  2009.     ret
  2010.  
  2011. noRandomDur:
  2012.     cmp    byte ptr [di+NotePercentVal],0
  2013.     je    no_note_percent
  2014.     mov    bl,ah
  2015.     shr    ah,1            ;divide by 2 (50%)    
  2016.     shr    ah,1            ;divide by 4 (25%)
  2017.     shr    ah,1            ;divide by 8 (12.5%)
  2018.     mov    cl,[di+NotePercentVal]
  2019.     xor    ch,ch
  2020.     xor    al,al
  2021.  
  2022. note_percent:
  2023.     add    al,ah
  2024.     loop    note_percent
  2025.     mov    [di+PercentDuration],al
  2026.  
  2027. no_note_percent:
  2028.     mov    [di+Duration],bl        ;save duration in ram control block
  2029.     ret
  2030.  
  2031. InstallDuration    endp
  2032. ;----------------------------------------------------------------------------
  2033.  
  2034. _speak    proc far        ;speak(pointer,dlength);
  2035. public    _speak
  2036.  
  2037. _speak    endp
  2038. ;----------------------------------------------------------------------------
  2039. ;send data to sound chip
  2040. ;ah-sound chip register
  2041. ;al-sound chip data
  2042.  
  2043. OutAdlib    proc    near
  2044.  
  2045.     mov    dx,ADLIBREGS        ;card address for regs
  2046.     xchg    al,ah            ;write chip register
  2047.     out    dx,al
  2048.     call    Wait33
  2049.     inc    dx            ;card address for data
  2050.     xchg    al,ah            ;send data to register
  2051.     out    dx,al            ;send to card
  2052.     call    Wait34
  2053.  
  2054.     ret
  2055. OutAdlib    endp
  2056. ;----------------------------------------------------------------------------
  2057. ;check for attenuation register overflows
  2058. ;ax has attenuation value
  2059.  
  2060. CheckWrap    proc    near
  2061.  
  2062.     cmp    ax,0
  2063.     jl    lessthanzero
  2064.     cmp    ax,03fh
  2065.     jg    greaterthan3f
  2066.     ret
  2067.  
  2068. lessthanzero:
  2069.     mov    al,0
  2070.     ret
  2071.  
  2072. greaterthan3f:
  2073.     mov    al,03fh
  2074.     ret
  2075.  
  2076. CheckWrap    endp
  2077. ;----------------------------------------------------------------------------
  2078. ;generate synchronization data for syncwait
  2079.  
  2080. syncgen    proc    near
  2081.  
  2082.     mov    al,presync        ;generate music tempo ticks
  2083.     add    al,globalTempo
  2084.     mov    presync,al
  2085.     jc    syncoverflow
  2086.     ret
  2087.  
  2088. syncoverflow:
  2089.     dec    notecntr        ;16th note frequency
  2090.     je    syncnow
  2091.     ret
  2092.  
  2093. syncnow:
  2094.     mov    al,notesync        ;established 16th/2
  2095.     mov    notecntr,al
  2096.     inc    syncbyte
  2097.     ret
  2098.  
  2099. syncgen    endp
  2100. ;----------------------------------------------------------------------------
  2101. ;return status of speech in ax
  2102.  
  2103. _vstatus    proc    far
  2104. public    _vstatus
  2105.  
  2106.     mov    ax,cs:doffset
  2107.     ret
  2108. _vstatus    endp
  2109. ;----------------------------------------------------------------------------
  2110. ;return status of a channel in ax
  2111. ;stack has channel to check
  2112.  
  2113. _sstatus    proc    far
  2114. public    _sstatus
  2115.     push    bp
  2116.     mov    bp,sp
  2117.  
  2118.     push    ds
  2119.     push    di
  2120.  
  2121.     mov    ax,cs
  2122.     mov    ds,ax
  2123.  
  2124.     mov    bx,word ptr [bp+6]    ;get sound code
  2125.     sub    bh,bh            ;bh<-0
  2126.     shl    bx,1
  2127.     mov    di,[bx+offset SchnlPtr]
  2128.     mov    al,[di+Duration]        ;put duration in al
  2129.     xor    ah,ah            ;return duration 
  2130.  
  2131.     pop    di
  2132.     pop    ds
  2133.  
  2134.     mov    sp,bp
  2135.     pop    bp
  2136.  
  2137.     ret
  2138. _sstatus    endp
  2139. ;----------------------------------------------------------------------------
  2140. ;delay for sound chip writes
  2141.  
  2142. Wait34    proc    near
  2143.  
  2144. IF    DEBUG
  2145.     push    dx
  2146.     inc    _NoWrites
  2147.     mov    dx,_NoWrites
  2148.     cmp    dx,MaxWrites
  2149.     jl    notmax
  2150.     mov    MaxWrites,dx
  2151.  
  2152. notmax:
  2153.     pop    dx
  2154. ENDIF
  2155.  
  2156.     push    ax
  2157.     push    cx
  2158.     push    dx
  2159.  
  2160.     mov    dx,0388h    
  2161.     mov    cx,23
  2162.  
  2163. waitlup1:
  2164.     in    al,dx
  2165.     loop    waitlup1
  2166.  
  2167.     pop    dx
  2168.     pop    cx
  2169.     pop    ax
  2170.     ret
  2171.  
  2172. Wait34    endp
  2173. ;----------------------------------------------------------------------------
  2174. ;delay for sound chip writes
  2175.  
  2176. Wait33    proc near
  2177.  
  2178.     push    ax
  2179.     push    cx
  2180.     push    dx
  2181.  
  2182.     mov    dx,0388h
  2183.     mov    cx,4
  2184.  
  2185. waitlup2:
  2186.     in    al,dx
  2187.     loop    waitlup2
  2188.  
  2189.     pop    dx
  2190.     pop    cx
  2191.     pop    ax
  2192.     ret
  2193.  
  2194. Wait33    endp
  2195. ;----------------------------------------------------------------------------
  2196. ;combine all levels of attenuation and check for overflows
  2197.  
  2198. CombineAttn    proc        ;combine all attenuation and stuff em
  2199. public  CombineAttn
  2200.  
  2201.     call    CombineOp2
  2202.     mov    bx,offset OPOFFSETS    ;get offset into chip
  2203.     add    bl,curchannel
  2204.     mov    cl,[bx]        ;cl has slot offset
  2205.  
  2206.     mov    ah,cl            ;get current channel
  2207.     add    ah,043h
  2208.     call    outadlib
  2209.  
  2210.     cmp    byte ptr [di+Algorithm],0
  2211.     je    attncombinedone
  2212.  
  2213.     call    CombineOp1
  2214.     mov    bx,offset OPOFFSETS    ;get offset into chip
  2215.     add    bl,curchannel
  2216.     mov    cl,[bx]        ;cl has slot offset
  2217.  
  2218.     mov    ah,cl            ;get current channel
  2219.     add    ah,040h
  2220.     call    outadlib
  2221.  
  2222. attncombinedone:
  2223.     ret
  2224.  
  2225. CombineAttn    endp
  2226. ;----------------------------------------------------------------------------
  2227. ;combine all attenuation and return it in al
  2228.  
  2229. CombineOp2    proc
  2230.  
  2231.     mov    al,[di+PatchAttn2]
  2232.     and    al,03fh        ;and off ksl    
  2233.     add    al,[di+AccentAttn]    ;add accent attenuation
  2234.     add    al,[di+sysAttn]        ;add system attenuation
  2235.     add    al,[di+ChannelAttn]    ;add channel attenuation
  2236.  
  2237.     cmp    byte ptr [di+Op2Velocity],0    ;any velocity ?    
  2238.     je    novelocity2
  2239.     mov    cl,[di+Op2Velocity]
  2240.     inc    cl
  2241.     xor    bh,bh
  2242.     mov    bl,[di+Velocity]
  2243.     shl    bx,cl
  2244.     sub    al,bh
  2245.  
  2246. novelocity2:
  2247.     cmp    al,03fh        ;check for wrap on top
  2248.     jna    checkalg        ;ok check if not stack    
  2249.     cmp    al,0            ;did it wrap below zero
  2250.     jl    wrapbottom        ;yes set to zero
  2251.     mov    al,03fh        ;no set to max
  2252.     jmp    short checkalg
  2253.  
  2254. wrapbottom:
  2255.     mov    al,0        
  2256.  
  2257. checkalg:
  2258.     mov    bl,[di+PatchAttn2]    ;save ksl and attn in shadow    
  2259.     and    bl,0c0h        ;and off attn        
  2260.     or    al,bl            ;combine attn and ksl
  2261.     ret
  2262.  
  2263. CombineOp2    endp
  2264. ;----------------------------------------------------------------------------
  2265. ;combine all attenuation and return it in al
  2266.  
  2267. CombineOp1    proc
  2268.  
  2269.     mov    al,[di+PatchAttn1]
  2270.     and    al,03fh        ;and off ksl
  2271.     cmp    byte ptr [di+Algorithm],0    ;only add this stuff if alg 1
  2272.     je    no_attn
  2273.     add    al,[di+AccentAttn]    ;add accent attenuation
  2274.     add    al,[di+sysAttn]        ;add system attenuation
  2275.     add    al,[di+ChannelAttn]    ;add channel attenuation
  2276.  
  2277. no_attn:
  2278.     cmp    byte ptr [di+Op1Velocity],0    ;any velocity ?    
  2279.     je    novelocity
  2280.     mov    cl,[di+Op1Velocity]
  2281.     inc    cl
  2282.     xor    bh,bh
  2283.     mov    bl,[di+Velocity]
  2284.     shl    bx,cl
  2285.     sub    al,bh
  2286.  
  2287. novelocity:
  2288.     cmp    al,03fh        ;check for wrap on top
  2289.     jna    stuffit
  2290.     cmp    al,0            ;did it wrap below zero
  2291.     jl    wrapbottom2        ;yes set to zero
  2292.     mov    al,03fh        ;no set to max
  2293.     jmp    short stuffit
  2294. wrapbottom2:
  2295.     mov    al,0        
  2296. stuffit:
  2297.     mov    bl,[di+PatchAttn1]    ;save ksl and attn in shadow    
  2298.     and    bl,0c0h        ;and off attn        
  2299.     or    al,bl            ;combine attn and ksl
  2300.     ret
  2301. CombineOp1    endp
  2302.  
  2303. ;----------------------------------------------------------------------------
  2304. ;clear sound process ram
  2305. ;di is assumed to be set for current channel
  2306.  
  2307. ClearSpram    proc    near
  2308.  
  2309.     push    es
  2310.     push    ax
  2311.     push    cx
  2312.  
  2313.     mov    cx,ds
  2314.     mov    es,cx
  2315.     mov    cx,SPRAMLEN-3
  2316.  
  2317.     sub    ax,ax
  2318.     push    di
  2319.     add    di,3            ;do not initialize the first 3 bytes
  2320.     shr    cx,1
  2321.     repnz    stosw
  2322.     adc    cx,cx
  2323.     repnz    stosb
  2324.     pop    di
  2325.  
  2326.     mov    byte ptr [di+Tempo],0ffh        ;max tempo
  2327.     mov    byte ptr [di+Priority],000h        ;reset priority
  2328.     mov    [di+PVector1],offset NullVector    ;set process vector
  2329.     mov    [di+PVector2],offset NullVector    ;set process vector
  2330.     mov    byte ptr [di+GateThreshold],1    ;default for gate threshold
  2331.  
  2332.     pop    cx
  2333.     pop    ax
  2334.     pop    es
  2335.  
  2336.     ret
  2337.  
  2338. ClearSpram    endp
  2339. ;----------------------------------------------------------------------------
  2340. ;write a patch to sound chip
  2341. ;si should be set to point at patch data
  2342.  
  2343. writepatch    proc    near
  2344.  
  2345.     mov    ah,020h        ;am/vib/eg/ksr/multi (miscmult)
  2346.     add    ah,cl
  2347.     lodsb
  2348.     call    outadlib
  2349.     mov    ah,023h        ;am/vib/eg/ksr/multi (miscmult)
  2350.     add    ah,cl
  2351.     lodsb
  2352.     call    outadlib
  2353.  
  2354.     mov    ah,0c0h        ;Feedback/algorithm
  2355.     add    ah,curchannel
  2356.     lodsb                ;si has patch source data
  2357.     call    outadlib
  2358.     and    al,01h        ;and off feedback
  2359.     mov    [di+Algorithm],al        ;save in shadow    
  2360.  
  2361.     mov    ah,0e0h        ;wavesel
  2362.     add    ah,cl
  2363.     lodsb                ;si has patch source data
  2364.     call    outadlib
  2365.  
  2366.     mov    ah,0e3h        ;wavesel
  2367.     add    ah,cl
  2368.     lodsb                ;si has patch source data
  2369.     call    outadlib
  2370.  
  2371.     mov    ah,040h        ;ksl/attenuation
  2372.     add    ah,cl
  2373.     lodsb                
  2374.     mov    [di+PatchAttn1],al    ;save ksl and attn in shadow    
  2375.     call    CombineOp1
  2376.     call    outadlib
  2377.  
  2378.     mov    ah,043h             ;ksl/attenuation
  2379.     add    ah,cl
  2380.     lodsb                
  2381.     mov    [di+PatchAttn2],al    ;save ksl and attn in shadow    
  2382.     call    CombineOp2
  2383.     call    outadlib
  2384.  
  2385.     mov    ah,060h        ;attack/decay
  2386.     add    ah,cl
  2387.     lodsb                ;si has patch source data
  2388.     call    outadlib
  2389.  
  2390.     mov    ah,063h        ;attack/decay
  2391.     add    ah,cl
  2392.     lodsb                ;si has patch source data
  2393.     call    outadlib
  2394.  
  2395.     mov    ah,080h        ;sustain/release
  2396.     add    ah,cl
  2397.     lodsb                ;si has patch source data
  2398.     call    outadlib
  2399.     mov    ah,083h        ;sustain/release
  2400.     add    ah,cl
  2401.     lodsb                ;si has patch source data
  2402.     call    outadlib
  2403.     ret
  2404.  
  2405. writepatch    endp
  2406. ;----------------------------------------------------------------------------
  2407. ;clear a currently running sound chip envelope
  2408. ;cl    has channel to clear 
  2409.  
  2410.  
  2411. clearenv    proc
  2412.  
  2413.     cmp    drummask,0
  2414.     je    no_drums
  2415.     cmp    cl,6
  2416.     jl    no_drums
  2417.     ret
  2418.  
  2419. no_drums:
  2420.     mov    bx,offset OPOFFSETS    ;get offset into chip
  2421.     mov    ch,cl
  2422.     add    bl,cl
  2423.     mov    cl,byte ptr [bx]    
  2424.  
  2425.     mov    ah,060h            ;modulator attack decay
  2426.     add    ah,cl
  2427.     mov    al,0ffh
  2428.     call    outadlib
  2429.  
  2430.     mov    ah,063h            ;carrier attack decay
  2431.     add    ah,cl
  2432.     mov    al,0ffh
  2433.     call    outadlib
  2434.  
  2435.     mov    ah,080h            ;modulator sustain release
  2436.     add    ah,cl
  2437.     mov    al,0ffh
  2438.     call    outadlib
  2439.  
  2440.     mov    ah,083h            ;carrier  sustain release
  2441.     add    ah,cl
  2442.     mov    al,0ffh
  2443.     call    outadlib
  2444.  
  2445.     mov    ah,0b0h            ;gate up
  2446.     add    ah,ch
  2447.     mov    al,000h
  2448.     call    outadlib
  2449.  
  2450.     mov    al,020h        ;gate down
  2451.     call    outadlib
  2452.  
  2453.     ret
  2454. clearenv    endp
  2455. ;----------------------------------------------------------------------------
  2456.  
  2457. ;***** process vector routines
  2458. ;process vectors routines that are executed on a channel basis
  2459. ;whenever they are turned on. They are executed at the interrupt
  2460. ;rate of the sound system and are independent of tempo
  2461.  
  2462. ;null return for process vectors
  2463. NullVector:
  2464.     ret
  2465.  
  2466. ;vibrato processing
  2467. DoVibrato:
  2468.     cmp    byte ptr [di+Vibdelaycount],0    ;check for 
  2469.     jz    okdovib
  2470.     dec    byte ptr [di+Vibdelaycount]
  2471.     ret
  2472.  
  2473. okdovib:
  2474.     mov    cl,[di+Vibprecount]          ;look for prescaler overfllow
  2475.     add    cl,[di+Vibpre]
  2476.     mov    [di+Vibprecount],cl
  2477.     jc    dovib
  2478.     ret
  2479.  
  2480. dovib:
  2481.     mov    bx,[di+Vibstep]
  2482.     dec    byte ptr [di+VibNewCount]
  2483.     jnz    cont
  2484.     xor    bx,0ffffh        ;shift sign
  2485.     inc    bx            ;finish off two's complement
  2486.     mov    [di+Vibstep],bx        ;save neg
  2487.     mov    al,[di+Vibcount]
  2488.     mov    [di+VibNewCount],al
  2489.  
  2490. cont:     
  2491.     mov    ax,[di+FreqLow]
  2492.     and    ax,03ffh
  2493.     add    ax,bx
  2494.     mov    [di+FreqLow],al
  2495.     mov    al,[di+Block]
  2496.     and    al,0fch
  2497.     or    al,ah
  2498.     mov    [di+Block],al
  2499.  
  2500.     mov    ah,0a0h        ;base of frequency low reg
  2501.     add    ah,curchannel        ;add channel offset
  2502.     mov    al,[di+FreqLow]
  2503.     call    outadlib
  2504.  
  2505.     mov    ah,0b0h        ;base of frequency high/block reg
  2506.     add    ah,curchannel        ;add channel offset
  2507.     mov    al,[di+Block]        ;freq high block data
  2508.     call    outadlib
  2509.     ret
  2510.  
  2511. TblMod:
  2512.     mov    al,[di+TpTmr]
  2513.     add    al,[di+TpPre]
  2514.     mov    [di+TpTmr],al
  2515.     jc    doTblMod
  2516.     ret
  2517. doTblMod:
  2518.     dec    byte ptr [di+tmoff]
  2519.     jns    TMpout
  2520.     mov    al,[di+tmlen]
  2521.     mov    [di+tmoff],al
  2522.  
  2523. TMpout:
  2524.     mov    ah,[di+TpOp]        ;al<-chip Hardware parameter base
  2525.     add    ah,Yamoff        ;adjust for this operator
  2526.     mov    al,[di+tmoff]        ;al<-index of Modulation data
  2527.     mov    bx,[di+tmbase]        ;bx<-base address of Modulation table
  2528.     xlat                ;al<-modulation data for chip
  2529.     call    outadlib
  2530.     ret
  2531.  
  2532. ;pitch delta processing
  2533. DoPitchDelta:
  2534.     mov    cl,[di+Pdeltcount]    ;check for prescaler overflow
  2535.     add    cl,[di+Pdeltpre]
  2536.     mov    [di+Pdeltcount],cl
  2537.     jc    okdodelta
  2538.     ret
  2539.  
  2540. okdodelta:
  2541.     mov    bl,[di+FreqLow]        ;get low byte of freq    
  2542.     mov    bh,[di+Block]        ;high byte and block
  2543.     and    bh,03h        ;clear out block
  2544.     mov    dl,[di+Block]
  2545.     mov    dh,dl
  2546.     and    dl,01ch        ;block only
  2547.     and    dh,020h        ;trigger only
  2548.  
  2549.     mov    cx,[di+Pdelt]        ;check for delta up or down
  2550.     or    cx,cx
  2551.     jl    pitchdown
  2552.  
  2553.     add    bx,cx            ;add increment to freq
  2554.     cmp    bx,02deh        ;highest note in current octave
  2555.     jl    pitchupdate        ;still ok
  2556.  
  2557.     shr    bx,1            ;it wrapped divide by two
  2558.     push    bx
  2559.     and    bx,03ffh
  2560.     jne    pdeltok2
  2561.  
  2562.     pop    bx
  2563.     inc    bx            ;dont let freq become zero
  2564.  
  2565. pdeltok2:
  2566.     pop    bx
  2567.  
  2568.     add    dl,04h        ;bump it up
  2569.     and    dl,01ch        ;wrap properly
  2570.     jmp    short pitchupdate        ;still ok
  2571.  
  2572. pitchdown:
  2573.     add    bx,cx            ;add increment to freq
  2574.     cmp    bx,0184h        ;check if it went past lowest freq
  2575.     jg    pitchupdate        ;if greater its ok
  2576.  
  2577.     shl    bx,1            ;it wrapped multiply by two
  2578.     push    bx
  2579.     and    bx,03ffh
  2580.     jne    pdeltok
  2581.  
  2582.     pop    bx
  2583.     dec    bx            ;dont let freq become zero
  2584.  
  2585. pdeltok:
  2586.     pop    bx
  2587.     sub    dl,04h        ;bump it up
  2588.     and    dl,01ch        ;wrap properly
  2589.  
  2590. pitchupdate:
  2591.     and    bx,03ffh        ;only ten freq bits
  2592.     mov    cx,dx            ;put block and trigger state in cx
  2593.     mov    ah,0a0h        ;base of frequency low reg
  2594.     add    ah,curchannel        ;add channel offset
  2595.     mov    al,bl
  2596.     call    outadlib
  2597.     mov    [di+FreqLow],al
  2598.  
  2599.     mov    ah,0b0h        ;base of frequency high/block reg
  2600.     add    ah,curchannel        ;add channel offset
  2601.     or    bh,cl            ;combine freq high and block
  2602.     or    bh,ch            ;combine freq high and trigger state
  2603.     mov    al,bh
  2604.     call    outadlib
  2605.     mov    [di+Block],al
  2606.     ret
  2607.  
  2608. Random:
  2609.     mov    ax,seed
  2610.     add    ax,9248h
  2611.     ror    ax,1
  2612.     ror    ax,1
  2613.     ror    ax,1
  2614.     mov    seed,ax
  2615.     ret
  2616.  
  2617.  
  2618.  
  2619. ;----------------------------------------------------------------------------
  2620. ;this is the opcode jump table
  2621. opcode_tbl:
  2622.     dw    SetLoop    ;80,no. of loops        set loop counter
  2623.     dw    TestLoop    ;81,labell              test loop counter and branch if not zero
  2624.     dw    StartVoice    ;82,string number       start a voice in some channel
  2625.     dw    SetGateThreshold    ;83
  2626.     dw    Branch    ;84,label            string branch
  2627.     dw    CallString    ;85,label            subroutine jump
  2628.     dw    StringReturn    ;86            subroutine return
  2629.     dw    OctaveOffset    ;87,no. of octaves        octave transpose
  2630.     dw    EOS        ;88            end of string
  2631.     dw    Rest        ;89,duration        rest
  2632.     dw    SetOplReg    ;8a,register,value        write directly to opl reg
  2633.     dw    NewNote    ;8b,notevalue,notelength    new note no trigger
  2634.     dw    NoteOffset    ;8c,note offset        set note offset
  2635.     dw    TableModOP    ;8d,pre8,len8,operator8,tblbase16
  2636.     dw    StopParse    ;8e,channel
  2637.     dw    EOS        ;8f
  2638.     dw    StuffPatch    ;90,patch number    install patch
  2639.     dw    PitchDelta    ;91,high,low        
  2640.     dw    ClearPitchDelta    ;92        clear pitch delta
  2641.     dw    FracPitch    ;93,lsb pitch offset
  2642.     dw    EOS        ;94
  2643.     dw    Vibrato    ;95,prescaler,shift,count,delay
  2644.     dw    EOS        ;96
  2645.     dw    EOS        ;97
  2646.     dw    EOS        ;98
  2647.     dw    EOS        ;99
  2648.     dw    SetPriority    ;9a,priority    set priority in current channel        
  2649.     dw    EOS        ;9b
  2650.     dw    InitSync    ;9c,sync mask    set string start sync    
  2651.     dw    WaitSync    ;9d        wait for sync
  2652.     dw    SetAccentAttn    ;9e,attenuation    set attenuation        
  2653.     dw    EOS        ;9f
  2654.     dw    Stay        ;a0,duration    do nothing for duration
  2655.     dw    Retrigger    ;a1,duration    retrigger current note    
  2656.     dw    EOS        ;a2
  2657.     dw    EOS        ;a3
  2658.     dw    NotePercent    ;a4,percent    set note percent
  2659.     dw    EOS        ;a5
  2660.     dw    SetMusicTempo    ;a6,tempo        set global tempo        
  2661.     dw    KillVector2    ;a7        kill vector 2
  2662.     dw    EOS        ;a8
  2663.     dw    SetTempo    ;a9,tempo        set local tempo
  2664.     dw    EOS        ;aa
  2665.     dw    SetChannelAttn    ;ab,attn        set channel attn    
  2666.     dw    SetsysAttn    ;ac,channel,attn    set attn in channel other than current
  2667.     dw    SetsysAttnDelta    ;ad,channel,delta    set delta amount in other than current channel
  2668.     dw    SetAmDepth    ;ae,depth
  2669.     dw    SetVibDepth    ;af,depth
  2670.     dw    SetSignedAttn    ;b0,attn        signed attn value    
  2671.     dw    EOS        ;b1
  2672.     dw    EOS        ;b2
  2673.     dw    KillChannel    ;b3,channel number
  2674.     dw    EOS        ;b4
  2675.     dw    RandomPitch    ;b5,16 bit and mask    add random amount to pitch
  2676.     dw    KillVector1    ;b6        stop vector 1
  2677.     dw    EOS        ;b7
  2678.     dw    EOS        ;b8        set up pitch bend vector
  2679.     dw    SetPitchBend    ;b9,value        set pitch bend value
  2680.     dw    getmusicTempo    ;ba        install global tempo in local
  2681.     dw    SNop        ;bb        nop
  2682.     dw    RandomDuration    ;bc,8 bit and mask    
  2683.     dw    tempodelta    ;bd,signedtempo    add to local tempo
  2684.     dw    EOS        ;be
  2685.     dw    MotorOn    ;bf,flag,table number
  2686.     dw    MotorOff    ;c0,        ;set motor flag    
  2687.     dw    DrumSetup    ;c1,patch1,patch2,patch3,freq1,freq2,freq3
  2688.     dw    DoDrum    ;c2,drum mask    trigger drum(s)    
  2689.     dw    DrumOff    ;c3        turn off drum mode
  2690.     dw    DrumAttn    ;c4,mask,attn
  2691.     dw    DrumFade    ;c5,mask,attn
  2692.     dw    DrumMasterAttn    ;c6,mask,attn
  2693.     dw    EOS        ;c7
  2694.     dw    SetAutoTempo    ;c8,flag
  2695.     dw    SetVelocity    ;c9,shift op1,shift op2    set velocity shift counts for op1 and op2
  2696.  
  2697. ;****************************************************************************
  2698. _TEXT    ends
  2699.  
  2700. end
  2701.  
  2702.