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