home *** CD-ROM | disk | FTP | other *** search
/ Dave Lowe: Ghostbusters I…C Atari ST-SS 1989.10.05 / Lowe_GhostbustersIIDiskC_AtariST-SS_1989.10.05.img / FXDRIVE.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-10-21  |  60.9 KB  |  2,926 lines

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