home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / sound / midi / mba.asm < prev    next >
Assembly Source File  |  1988-03-20  |  179KB  |  3,938 lines

  1.     TITLE    Modules for Modular Sequencer
  2.     NAME    MBA
  3.     .SALL
  4. ;==============================================================
  5. ; MusicBox Modular Sequencer, Version 2
  6. ; modules code
  7. ;--------------------------------------------------------------
  8. ; author: John Dunn
  9. ; date:   03/07/86
  10. ; update: 03/20/88
  11. ;--------------------------------------------------------------
  12. ; COPYRIGHT (C) 1986 John Dunn, All Rights Reserved 
  13. ; Entered into the Public Domain, March 20, 1988
  14. ;
  15. ; Use and copying of this software and preparation of derivative works
  16. ; based upon this software are permitted.  Any distribution of this
  17. ; software or derivative works must comply with all applicable United
  18. ; States export control laws.
  19. ; This software is made available AS IS, and the author makes no warranty 
  20. ; about the software, its performance, or its conformity to any specification.
  21. ; Any person obtaining a copy of this software is requested to send their
  22. ; name and address address to:
  23. ;
  24. ;       John Dunn, Senior Research Fellow
  25. ;       Time Arts Inc.
  26. ;       3436 Mendocino Ave.
  27. ;       Santa Rosa, CA 95401
  28. ;
  29. ;==============================================================
  30.         include    order.asm
  31. ;--------------------------------------------------------------
  32.         include equates.asm
  33. ;==============================================================
  34. BUFPA   SEGMENT
  35.         if      debug
  36.         db      7fffh dup (?)
  37.         db      7fffh dup (?)
  38.         else
  39.         db      7fffh dup (0)
  40.         db      7fffh dup (0)
  41.         endif
  42. BUFPA   ENDS
  43. ;--------------------------------------------------------------
  44. BUFSP   SEGMENT
  45.         if      debug
  46.         db      4096 dup (?)
  47.         else
  48.         db      4096 dup (0)
  49.         endif
  50. BUFSP   ENDS
  51. ;--------------------------------------------------------------
  52. BUFFS   SEGMENT
  53.         if      debug
  54.         db      7fffh dup (?)
  55.         db      7fffh dup (?)
  56.         else
  57.         db      7fffh dup (0)
  58.         db      7fffh dup (0)
  59.         endif
  60. BUFFS   ENDS
  61. ;--------------------------------------------------------------
  62. BUFTU   SEGMENT
  63.         if      debug
  64.         db      4096 dup (?)
  65.         else
  66.         db      4096 dup (0)
  67.         endif
  68. BUFTU   ENDS
  69. ;==============================================================
  70. _DATA   SEGMENT
  71.         ASSUME DS:DGROUP, CS:_TEXT
  72. ;--------------------------------------------------------------
  73.         extrn   ticka:byte,tickis:byte,fastflg:byte
  74.         extrn   _header:byte
  75.         extrn   varsav:word,cmdflg:byte,special:word,cmdcnt:byte
  76.         extrn   locsav:word,cmdloc:word,vpage:word,curadr:word
  77.         extrn   midip:byte,valflg:byte,asensf:byte
  78.         extrn   @zero:near,magflg:byte,usrflg:byte,holdv:word
  79.         extrn   colr:byte,lodflg:byte
  80.         extrn   modnum:byte,doesc:word,clrchf:byte,curonf:byte
  81. ;--------------------------------------------------------------
  82.         if      debug
  83.         extrn   show0:word,show1:word,show2:word,show3:word
  84.         endif
  85. ;--------------------------------------------------------------
  86.         public midisf,midixsf,mpmodf,mpadrf,mpadr
  87.         public mmcount,mmtick,mmreset,mmstart
  88. ;--------------------------------------------------------------
  89. midisf  db      0                       ; 0=no sync, 1=send sync
  90. midixsf db      0                       ; 0=not xtrn sync, NZ=is
  91. mpmodf  db      1                       ; master program mode flag
  92. mpadrf  db      0                       ; nz if change in prog address
  93. mpadr   db      0                       ; master program address
  94. mmcount dw      0                       ; master measure count
  95. mmtick  dw      1                       ; ticks left in current measure
  96. mmreset db      1                       ; master measure reset flag
  97. mmstart db      1                       ; master measurd start flag
  98. ;--------------------------------------------------------------
  99.         public rseed,rhold,notetbl,notes
  100.         public xcax,xcbx,xccx,xcdx
  101.         public temp0,temp1,temp2,temp3
  102. ;--------------------------------------------------------------
  103. rseed   dw      0                       ; random number seed
  104. rhold   db      0                       ; nz = holding          
  105. notes   dw      4186,4435,4699,4978,5274,5588,5920,6272,6645,7040,7459,7902
  106. ;
  107. ;--------------------------------------------------------------
  108. ; notes --> clocks
  109. ;
  110. ; nv =      0    1   2   3   4   5   6   7
  111. ;
  112. notetbl db 192, 96, 48, 24, 12,  6,  3,  2 ; normal
  113.         db 128, 64, 32, 16,  8,  4,  2,  2 ; dotted
  114.         db 255,144, 72, 36, 18,  9,  5,  3 ; tripplett
  115. ;--------------------------------------------------------------
  116. ;
  117. xcax    dw      0       ; register storage, used by xcall
  118. xcbx    dw      0 
  119. xccx    dw      0
  120. xcdx    dw      0
  121. ;
  122. temp0   db      0       ; temp storage, use within module
  123. temp1   db      0
  124. temp2   db      0
  125. temp3   db      0
  126. ;--------------------------------------------------------------
  127. ; the following are saved/loaded
  128. ;--------------------------------------------------------------
  129.         public interv,mvlsav,mvlnum,mute,mutef,mprstf
  130.         public mbeat,mnote,mtempo,mclocks
  131.         public ctrlmap,pcva,pcvb,pcvc,pcvd,pcve,pcvf
  132. ;--------------------------------------------------------------
  133. mvlsav  equ     $                       ; start of mod values to save
  134. interv  db      64 dup(0)               ; intervals for modulation
  135.         ;
  136. mprstf  db      0                       ; master program reset flag
  137. mute    dw      -1                      ; channel mute flags
  138. mutef   db      1                       ; 1=mute, 0=solo flag
  139.         ;
  140. mbeat   db      4                       ; master beats/measure
  141. mnote   db      24                      ; master note value
  142. mtempo  db      78H                     ; master tempo
  143. mclocks dw      96                      ; master clocks/measure
  144.         ;
  145. pcva    db      16 dup (0)              ; values sent to controller
  146. pcvb    db      16 dup (0)              ; values sent to controller
  147. pcvc    db      16 dup (0)              ; values sent to controller
  148. pcvd    db      16 dup (0)              ; values sent to controller
  149. pcve    db      16 dup (0)              ; values sent to controller
  150. pcvf    db      16 dup (0)              ; values sent to controller
  151. pcvg    db      16 dup (0)              ; values sent to controller
  152. pcvh    db      16 dup (0)              ; values sent to controller
  153. pcvx    db      16 dup (0)              ; values sent to controller
  154. pcvy    db      16 dup (0)              ; values sent to controller
  155. pcvz    db      16 dup (0)              ; values sent to controller
  156.         ;
  157. ctrlmap db      7,1,2,3,4,5,64,65       ; midi controller map
  158. ctrlmpp db      7,1,2,3,4,5,64,65       ; midi controller map
  159.         ;
  160. mvlnum  equ     $-mvlsav                ; number of mod values to save
  161. ;--------------------------------------------------------------
  162. _DATA   ENDS
  163. ;==============================================================
  164. ; Module Execution Code
  165. ; All inputs are word pointers to output word values.
  166. ; All outputs are binary words, with only the ls byte output.
  167. ;==============================================================
  168. ; EQUATES for modules
  169. ;
  170. vseg    equ 4                   ; offset to video seg addr
  171. vaddr   equ 6                   ; offset to video page addr
  172. outn    equ 8                   ; offset to output
  173. numvar  equ 10                  ; number of input variables
  174. var0    equ 12                  ; offset to variable 0
  175. var1    equ var0+2              ; offset to variable 1
  176. var2    equ var1+2              ; etc.
  177. var3    equ var2+2              ; etc.
  178. var4    equ var3+2              ; etc.
  179. var5    equ var4+2              ; etc.
  180. var6    equ var5+2              ; etc.
  181. var7    equ var6+2              ; etc.
  182. var8    equ var7+2              ; etc.
  183. var9    equ var8+2              ; etc.
  184. var10   equ var9+2              ; etc.
  185. var11   equ var10+2             ; etc.
  186. var12   equ var11+2             ; etc.
  187. var13   equ var12+2             ; etc.
  188. var14   equ var13+2             ; etc.
  189. var15   equ var14+2             ; etc.
  190. var16   equ var15+2             ; etc.
  191. var17   equ var16+2             ; etc.
  192. var18   equ var17+2             ; etc.
  193. var19   equ var18+2             ; etc.
  194. var20   equ var19+2             ; etc.
  195. var21   equ var20+2             ; etc.
  196. var22   equ var21+2             ; etc.
  197. slewe   equ var22               ; programmer slew buffer
  198. slewf   equ slewe+6             ; etc.
  199. slewg   equ slewf+6             ; etc.
  200. slewh   equ slewg+6             ; etc.
  201. pubuf   equ slewh+6             ; programmer undo buffer
  202. psbuf   equ pubuf+16            ; programmer save buffer
  203.         ;
  204. onflg   equ 1                   ; bit mask for note-on
  205. offlg   equ 2                   ; bit mask for note-off
  206. sentf   equ 4                   ; bit mask for note-sent
  207. ;--------------------------------------------------------------
  208. _TEXT   SEGMENT
  209.     ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: NOTHING
  210. ;--------------------------------------------------------------
  211.         extrn   ticks:word,loops:word,seconds:word,secondf:byte
  212.         extrn   todec:near,tonote:near,startm:near
  213.         extrn   midatix:byte,misend:byte
  214.         extrn   _cancel:near,workx:near,split:near
  215.         extrn   turnon:near,turnoff:near,noop:near,curon:near,curoff:near
  216.         extrn   mstart:byte,mstop:byte,mcont:byte,midata:byte,miflag:byte
  217.         extrn   sendm:near,alloff:near,tomidi:near,allmidi:near,allclr:near
  218.         extrn   tstmob:near,allclr:near,_mpuinf:byte,_mpuinm:byte
  219. ;==============================================================
  220.         include    macros.asm
  221. ;==============================================================
  222. ; THE MODULES
  223. ;==============================================================
  224.  
  225. ;==============================================================
  226. ; Global Parameter Module
  227. ; (only one copy available)
  228. ; Output: Stop flag (is high for 1 cycle prior to HLT)
  229. ; Inputs:
  230. ; 0: NZ Sets master programmer reset flag
  231. ; 1: value --> master programmer address
  232. ; 2: NZ sets menu for solo, 0 sets mute
  233. ; 3: NZ sets Program-mode flag to Program, Z sets to Play
  234. ; 4: Beats Per measure, change recaluclates tick-count "ticka"
  235. ; 5: Note value for above, change recaluclates tick-count
  236. ; 6: Tempo, change reclalculates tick-count
  237. ; 7: Reset RNG.  Any change sets seed to new value
  238. ; 8: bit 0 set MIDI output sync, bit 1 sets input sync
  239. ; 9: NZ transition causes HLT, if FF then BYE 
  240. ; 10 : initialized flag
  241. ; 10+: 
  242. ; 11 : Copy of ticks remaining
  243. ; 11+: Transition (tick) flags
  244. ;--------------------------------------------------------------
  245.         public _alpha
  246. _alpha: cmp     byte ptr var10[di],0ABh  ; initialized yet?
  247.         jz      alphaz                   ; yes, go on
  248.         mov     byte ptr var10[di],0ABh  ; no, set init values
  249.         initv   var3,1          ; prog  <-- 1
  250.         initv   var4,4          ; beats <-- 4
  251.         initv   var5,3          ; note  <-- 3
  252.         initv   var6,78h        ; tempo <-- 78h 
  253. alphaz:
  254. ;--------------------------------------------------------------
  255. ; 0: NZ Sets master programmer reset flag, Z releases
  256. ;
  257.         mov     al,mprstf       ; get master reset flag
  258.         and     al,0FEH         ; clear alpha reset bit
  259.         testv   var0,-1         ; check for Z/NZ
  260.         jz      alpha0a         ; branch if Z
  261.         or      al,1            ; ...if NZ
  262.         mov     mmcount,0       ; clear measure count
  263.         mov     cs:seconds,0    ; reset clock
  264.         mov     cs:secondf,2    ; flag to show it
  265.         mov     mmtick,1        ; reset to 1st note in measure
  266. alpha0a:mov     mprstf,al       ; set/reset the flag
  267. ;--------------------------------------------------------------
  268. ; 1: value --> master programmer address
  269. ;
  270.         getv    al,var1         ; get the value
  271.         cmp     al,mpadr        ; any change
  272.         mov     ah,0            ; setup to clear change flag
  273.         jz      alpha1a         ; no, branch
  274.         mov     ah,1            ; yes, set change flag
  275.         mov     mpadr,al        ; set new address
  276. alpha1a:mov     mpadrf,ah       ; flag change/no change
  277. ;--------------------------------------------------------------
  278. ; 2: NZ sets menu for solo, 0 sets mute
  279. ;
  280.         mov     al,1            ; set for mute
  281.         testv   var2,-1         ; get the flag
  282.         jz      alpha2a         ; branch if solo
  283.         mov     al,0            ; else set for solo
  284. alpha2a:mov     mutef,al        ; set it
  285. ;--------------------------------------------------------------
  286. ; 3: NZ sets Program-mode flag to Program, Z sets to Play
  287. ;
  288.         testv   var3,-1         ; check for Z/NZ
  289.         mov     al,0            ; ...if Z
  290.         jz      alpha3a         ; branch if Z
  291.         inc     al              ; ...if NZ
  292. alpha3a:mov     mpmodf,al       ; set/reset the flag
  293. ;--------------------------------------------------------------
  294. ; 4: Beats Per measure, change recaluclates 
  295. ;
  296.         getv    al,var4         ; get beats per measure
  297.         cmp     mbeat,al        ; compare with master beats/measure
  298.         jz      alpha4z         ; boogie if no change
  299.         or      al,al           ; don't allow 0 either
  300.         jz      alpha4z         ; /
  301.         mov     mbeat,al        ; else set new beats/measure
  302.         mov     ah,mnote        ; get clocks per note
  303.         mul     ah              ; ax = clocks/measure        
  304.         mov     mclocks,ax      ; put away
  305. alpha4z:
  306. ;--------------------------------------------------------------
  307. ; 5: Note value for above, change recaluclates
  308. ;
  309.         getv    bl,var5         ; get note value
  310.         cmp     mnote,bl        ; compare with master note value
  311.         jz      alpha5z         ; boogie if no change
  312.         cmp     bl,5            ; 0-5 allowed
  313.         ja      alpha5z         ; do nothing if > 6
  314.         mov     bh,0            ; else xlate to clocks
  315.         add     bx,offset dgroup:notetbl; /
  316.         mov     al,[bx]         ; al = clocks
  317.         mov     mnote,al        ; set new clocks/note
  318.         mov     ah,mbeat        ; get beats/measure
  319.         mul     ah              ; ax = clocks/measure        
  320.         mov     mclocks,ax      ; put away
  321. alpha5z:
  322. ;--------------------------------------------------------------
  323. ; 6: Tempo, change reclalculates tick-count
  324. ;
  325.         getv    dl,var6         ; get beats per measure
  326.         mov     fastflg,0       ; clear fast flag
  327.         cmp     dl,0ffh         ; fast as possible?
  328.         jnz     alpha6b         ; no, branch
  329.         mov     fastflg,1       ; yes, set flag 
  330. alpha6b:cmp     mtempo,dl       ; compare with master tempo
  331.         jz      alpha6z         ; boogie if no change
  332.         mov     mtempo,dl       ; else set new value
  333.         cmp     dl,5            ; must be > 5
  334.         ja      alpha6a         ; branch if ok
  335.         mov     dl,6            ; else make it 6
  336. alpha6a:mov     ax,1456         ; calculate loop ticks
  337.         div     dl              ; /
  338.         mov     ticka,al        ; put it in the timer
  339. alpha6z:
  340. ;--------------------------------------------------------------
  341. ; 7: Reset RNG.  Any change sets seed to new value
  342. ;
  343.         getv    al,var7         ; get rng seed
  344.         or      al,al           ; is zero?
  345.         jz      alpha7z         ; yes, don't set new seed
  346.         ror     al,1            ; 1 --> 80H, etc.
  347.         mov     ah,al           ; 255 possible seeds
  348.         mov     rseed,ax        ; set the new seed
  349. alpha7z:mov     rhold,al        ; set/clear hold flag
  350. ;--------------------------------------------------------------
  351. ; 8: bit 0 sets output sync, bit 1 sets input sync
  352. ;
  353.         test    valflg,-1       ; inputting values now?
  354.         jnz     alpha8d         ; yes, don't do nothin 
  355.         getv    dl,var8         ; get the flag
  356.         mov     ax,0            ; clear sync flags
  357.         test    dl,1            ; output sync?
  358.         jz      alpha8a         ; no, branch
  359.         mov     al,1            ; yes, set out sync flag
  360. alpha8a:test    dl,2            ; input sync?
  361.         jz      alpha8b         ; no, branch
  362.         mov     ah,1            ; yes, set input sync flag
  363. alpha8b:mov     midisf,al       ; set sync out flag
  364.         mov     midixsf,ah      ; set external sync flag
  365.         test    dl,6            ; defeat active sensing?
  366.         mov     al,1            ; ...setup for no defeat
  367.         jz      alpha8c         ; no, branch
  368.         mov     al,0            ; yes, clear active sensing flag
  369. alpha8c:mov     asensf,al       ; set the flag
  370. alpha8d:
  371. ;--------------------------------------------------------------
  372. ; 9: NZ transition causes HLT.
  373. ;    Value of FF causes BYE.
  374. ;
  375.         tick    var9,var11+1   ; clock tick
  376.         jc      alpha9c        ; /
  377.         jmp     alpha9z        ; boogie if no tick
  378. alpha9c:
  379.         getv    al,var9        ; check for FF (split)
  380.         cmp     al,0ffh        ; wanna split?
  381.         jz      alpha9e        ; yes, do it
  382.         jmp     alpha9a        ; no, branch to HLT
  383. alpha9e:
  384.         call    alloff          ; process all notes off
  385.         jmp     split           ; become history
  386. alpha9a:                        ; HLT
  387.         mov     bx,6E0H         ; menu text offset
  388.         call    turnon          ; turn on the menu text
  389.         or      mprstf,2        ; set HLT flag
  390.         mov     al,0fch         ; send MIDI STOP command
  391.         call    allmidi         ; /
  392. alpha9z:
  393. ;--------------------------------------------------------------
  394. ; display number of calculation clocks available
  395. ;
  396. alpha11:mov     al,tickis       ; get ticks remaining
  397.         cmp     al,var11[di]    ; same as before?
  398.         jz      alpha11z        ; yes, boogie
  399.         mov     var11[di],al    ; no, save new value
  400.         gettag                  ; es:bx = screen addr of tag
  401.         or      al,al           ; test for bottoming out
  402.         jz      alpha11a        ; branch if Z
  403.         and     byte ptr es:(160*13-1)[bx],0F7H; lowlight if NZ
  404.         jmp     short alpha11b  ; then branch around highlight
  405. alpha11a:or     byte ptr es:(160*13-1)[bx],8; highlight if Z
  406. alpha11b:tohex                  ; convert to hex word
  407.         mov     es:(160*13)[bx],ah; put to the screen
  408.         mov     es:(160*13+2)[bx],al; /
  409. alpha11z:
  410. ;--------------------------------------------------------------
  411. ; shunt stop flag to output
  412. ;
  413. alphax: mov     al,mprstf       ; get the flag
  414.         shr     al,1            ; HLT is bit 2
  415.         putn    al              ; send it out
  416.         nextl                   ; show it
  417.  
  418. ;==============================================================
  419. ; absolute time counter
  420. ; output: ticks count AND input0
  421. ; input: 0: hold, 1: period,  2: AND mask
  422. ;
  423. ;--------------------------------------------------------------
  424.         public _beta
  425. _beta:  hold    var0            ; hold?
  426.         jz      beta0           ; no, branch
  427.         mov     al,0            ; yes, clear clock
  428.         jmp     short betax     ; exit
  429.         ;
  430. beta0:  mov     ax,cs:ticks     ; get timer value
  431.         getv    cl,var1         ; get period
  432.         shr     ax,cl           ; bump
  433.         getv    ah,var2         ; get AND mask
  434.         and     al,ah           ; AND them
  435. betax:  putn    al              ; send to output
  436.         nextl
  437. ;==============================================================
  438. ; seconds counter
  439. ; output: seconds count AND input0
  440. ; input: 0: hold/reset
  441. ;        1: nz = minutes
  442. ;        2:  offset
  443. ;
  444. ;--------------------------------------------------------------
  445.         public _secs
  446. _secs:  hold    var0            ; hold?
  447.         jz      secs0           ; no, branch
  448.         mov     ax,cs:seconds   ; yes, get current second count
  449.         mov     var2[di],ax     ; set new time offset
  450.         jmp     short secsz     ; exit
  451.         ;
  452. secs0:  mov     ax,cs:seconds   ; get timer value
  453.         sub     ax,var2[di]     ; subtract offset
  454.         mov     dx,0            ; double word
  455.         getv    ch,var1         ; get clock flag
  456.         test    ch,-1           ; leave free count?
  457.         jz      secsx           ; yes, branch
  458.         mov     bx,60           ; no,/60
  459.         div     bx              ; /
  460.         cmp     ch,1            ; want seconds?
  461.         jnz     secsx           ; no, do minutes
  462.         mov     al,dl           ; yes, mod for secs
  463. secsx:  putn    al              ; send to output
  464.         mov     colr,yellow     ; set color to yellow
  465.         mov     es,4[di]        ; get seg addr
  466.         mov     bx,6[di]        ; get module screen address
  467.         add     bx,478          ; point to readout
  468.         call    todec           ; do it
  469.         mov     colr,green      ; fix it back to green
  470.         ;
  471.         cmp     ch,1            ; want seconds?
  472.         jnz     secsz           ; no, branch
  473.         mov     byte ptr es:[bx],':'; yes, print ':' 
  474. secsz:  nextv
  475. ;==============================================================
  476. ; simple loop counter
  477. ; output: loop count AND input0
  478. ; input: 0: hold, 1: period,  2: AND mask
  479. ;
  480. ;--------------------------------------------------------------
  481.         public _lambda
  482. _lambda:hold    var0            ; hold?
  483.         jz      lambda0         ; no, branch
  484.         mov     al,0            ; yes, clear clock
  485.         jmp     short lambdax   ; exit
  486.         ;
  487. lambda0:mov     ax,cs:loops     ; get count
  488.         getv    cl,var1         ; get period
  489.         shr     ax,cl           ; bump
  490.         getv    ah,var2         ; get AND mask
  491.         and     al,ah           ; AND them
  492. lambdax:putn    al              ; send to output
  493.         nextl
  494. ;==============================================================
  495. ; measure clock
  496. ; output: measure start strobe, with delay
  497. ; input:
  498. ; 0:    Hold
  499. ; 1:    delay value
  500. ; 2x:   countdown
  501. ; 2z:   trip flag
  502. ;--------------------------------------------------------------
  503.         public  _mclk
  504. _mclk:  mov     byte ptr outn[di],0; clear output
  505.         hold    var0            ; hold?
  506.         jnz     mclkx           ; yes, exit
  507.         ;
  508.         mov     al,var2+1[di]   ; trip flag on?
  509.         or      al,mmstart      ; or measure start?
  510.         jz      mclkx           ; no, exit
  511.         ;
  512.         test    byte ptr var2+1[di],1; trip flag?
  513.         jnz     mclk0                ; yes, go countdown
  514.         getv    al,var1              ; no, get delay value
  515.         inc     al                   ; 0 --> 1
  516.         mov     var2[di],al          ; set new countdown
  517.         mov     byte ptr var2+1[di],1; set trip flag
  518.         ;
  519. mclk0:  dec     byte ptr var2[di]    ; count down
  520.         jnz     mclkx                ; exit if not end of count
  521.         mov     byte ptr var2+1[di],0; else clear trip flag
  522.         mov     byte ptr outn[di],1  ; set output
  523.         ;
  524. mclkx:  nextl                   ; exit
  525. ;==============================================================
  526. ; measure clock
  527. ; output: clock strobe
  528. ; input: 0: reset, 1: count, 2x:countdown timer, 2z: copy of count
  529. ;
  530. ;--------------------------------------------------------------
  531.         public _mclock
  532. _mclock:hold    var0            ; hold?
  533.         jz      mclock2         ; no, branch
  534.         getv    al,var1         ; yes, reset
  535.         mov     ah,al           ;  /
  536.         mov     var2[di],ax     ; /
  537.         jmp     short mclockz   ; exit with output=0
  538.         ;
  539. mclock2:test    mmstart,1       ; measure start?
  540.         jz      mclockz         ; no, exit
  541.         mov     ah,1            ; yes, set output=1
  542.         ;
  543.         getv    al,var1         ; get current count
  544.         cmp     al,var2+1[di]   ; same as before?
  545.         jz      mclock1         ; yes, branch
  546.         mov     var2+1[di],al   ; no, set new count
  547.         ;
  548. mclock0:mov     al,var2+1[di]   ; reset timer
  549.         mov     var2[di],al     ; / 
  550.         jmp     short mclockx   ; exit
  551.         ;
  552. mclock1:dec     byte ptr var2[di]; tick
  553.         jz      mclock0          ; branch if end of count
  554. mclockz:mov     ah,0             ; else set output=0
  555.         ;
  556. mclockx:mov     outn[di],ah      ; send output
  557.         nextl                    ; exit
  558. ;==============================================================
  559. ; simple loop counter
  560. ; output: clock strobe
  561. ; input: 0: reset, 1: count, 2: offset
  562. ;        3x:countdown timer, 3z: copy of count
  563. ;--------------------------------------------------------------
  564.         public _gamma
  565. _gamma: testv   var1,-1         ; clock = 0
  566.         jz      gammaz          ; yes, just exit
  567.         hold    var0            ; hold?
  568.         jz      gamma0          ; no, branch
  569.         mov     al,byte ptr cs:loops; get count
  570.         and     al,1            ; /
  571.         mov     var3[di],al     ; reset clock counters
  572.         jmp     short gammaz    ; split
  573.         ;
  574. gamma0: getv    ah,var1         ; get current count
  575.         cmp     ah,var3+1[di]   ; same as before?
  576.         jz      gamma1          ; yes, branch
  577.         cmp     ah,1            ; set to 1?
  578.         jnz     gamma3          ; no, branch
  579.         mov     ah,2            ; yes, set to 2
  580. gamma3: mov     al,byte ptr cs:loops; get count
  581.         and     al,1            ; /
  582.         mov     var3[di],ax     ; /
  583.         ;
  584. gamma1: getv    al,var2         ; get offset trigger
  585.         cmp     al,ah           ; out of range?
  586.         jb      gamma4          ; no, branch
  587.         mov     al,0            ; yes, zip it
  588. gamma4: cmp     al,var3[di]     ; same as count?
  589.         jnz     gamma2          ; no, branch
  590.         mov     byte ptr outn[di],1; yes, set output flag
  591.         ;
  592. gamma2: inc     byte ptr var3[di]; tick
  593.         cmp     ah,var3[di]     ; reached count?
  594.         jnz     gammaz          ; no, exit
  595.         mov     byte ptr var3[di],0; yes, reset timer
  596. gammaz: nextt                   ; exit
  597.  
  598. ;==============================================================
  599. ; simple loop counter
  600. ; output: clock strobe
  601. ; input: 0: reset, 1: count
  602. ;        2x:countdown timer
  603. ;--------------------------------------------------------------
  604.         public _muclk
  605. _muclk: testv   var1,-1         ; clock = 0
  606.         jz      muclkz          ; yes, just exit
  607.         hold    var0            ; hold?
  608.         jnz     muclk0          ; yes, reset & exit
  609.         ;
  610.         dec     byte ptr var2[di]; count down
  611.         jnz     muclkz          ; exit if not 0
  612.         mov     byte ptr outn[di],1; set output
  613. muclk0: getv    al,var1         ; else get count
  614.         mov     var2[di],al     ; put it away
  615. muclkz: nextt                   ; exit
  616. ;==============================================================
  617. ; Note Clock
  618. ; output: 0/Veloc input value
  619. ; inputs:
  620. ; 0:    Reset & hold
  621. ; 1:    Sync pulse
  622. ; 2:    Note value 0-7, +10H tripplett, +20H dotted
  623. ; 3:    Sustain value 0-255
  624. ; 4:    Clock offset value
  625. ; 5:    Velocity value
  626. ; 6x:   note countdown
  627. ; 6+:   nz = wait for sync with measure
  628. ; 7x:   note-on clocks
  629. ; 7+:   AB = has been initialized
  630. ; 8x:   nz = sync countdown flag
  631. ; 8+:   offset value changed flag
  632. ;--------------------------------------------------------------
  633.  
  634.         public _clock,_klock
  635. _klock: nop                             ; same routine, different address
  636. _clock:
  637.         cmp     byte ptr var7+1[di],0ABH; initialized yet?
  638.         jz      clock00                 ; yes, branch
  639.         mov     byte ptr var7+1[di],0ABH; no, initialize
  640.         ;
  641.         initv   var1,1                  ; sync
  642.         initv   var2,3                  ; note
  643.         initv   var5,1                  ; velocity
  644.         mov     word ptr var6[di],0     ; flags
  645.         mov     byte ptr var7[di],0     ; flags
  646.         ;
  647. clock00:hold    var0            ; hold?
  648.         jnz     clock01                 ; yes, go do it
  649.         getv    al,var4                 ; change in offset value?
  650.         cmp     al,var8+1[di]           ; /
  651.         jz      clock0                  ; no, branch
  652.         ;
  653. clock01:getv    al,var4                 ; get sync offset
  654.         mov     var8+1[di],al           ; clear change flag
  655.         inc     al                      ; bump sync count so 0 --> 1
  656.         mov     var6+1[di],al           ; set up sync offset count
  657.         mov     byte ptr outn[di],0     ; clear output
  658.         mov     byte ptr var6[di],0     ; clear note count
  659.         jmp     clockx                  ; exit
  660.         ;
  661. clock0: test    byte ptr var6+1[di],-1  ; waiting for sync?
  662.         jz      clock1                  ; no, branch
  663.         getv    al,var1                 ; sync start?
  664.         or      al,byte ptr var8[di]    ; or countdown?
  665.         jnz     clock0a                 ; yes, branch
  666.         jmp     clockx                  ; no, exit
  667.         ;
  668. clock0a:mov     byte ptr var8[di],1     ; set offset flag    
  669.         dec     byte ptr var6+1[di]     ; countdown sync
  670.         jz      clock0b                 ; branch on if 0
  671.         jmp     clockx                  ; else exit  
  672. clock0b:mov     byte ptr var8[di],0     ; clear offset flag
  673.         ;        
  674. clock1: cmp     byte ptr var6[di],0     ; at end of note?
  675.         jz      clock1b                 ; yes, branch
  676.         jmp     clock2                  ; no, countdown
  677.         ;
  678. clock1b:getv    bl,var2                 ; get note value
  679.         mov     dl,bl                   ; save in dl for dot/tripplet
  680.         and     bl,7                    ; mask
  681.         mov     bh,0                    ; else xlate to clocks
  682.         add     bx,offset dgroup:notetbl; /
  683.         test    dl,10h                  ; triplett?
  684.         jz      clock1c                 ; no, branch
  685.         add     bx,8                    ; yes, bump table addr
  686.         jmp     short clock1d           ; branch around dot
  687. clock1c:test    dl,20h                  ; dot?
  688.         jz      clock1d                 ; no, branch
  689.         add     bx,16                   ; yes, bump table addr
  690. clock1d:;
  691.         mov     cl,[bx]                 ; cl = clocks
  692.         getv    dl,var3                 ; dl = sustain value
  693.         ;
  694.         mov     al,1                    ; al = 1 clock
  695.         cmp     dl,0                    ; sustain = min
  696.         jz      clock1e                 ; yse, exit sust.
  697.         ;
  698.         mov     al,cl                   ; al = nv (clocks)
  699.         cmp     dl,0ffh                 ; sustain = max
  700.         jz      clock1e                 ; yes, exit legato
  701.         ;
  702.         mul     dl                      ; ax = nv * sust
  703.         mov     al,ah                   ; al = nv * sust / 256
  704.         or      al,al                   ; /
  705.         jnz     clock1e                 ; go if > 0
  706.         inc     al                      ; else make 1
  707.         ;
  708. clock1e:mov     var6[di],cl             ; set new note value
  709.         sub     cl,al                   ; off = nv - on
  710.         mov     var7[di],cl             ; set new off-time
  711.         jmp     short clock2a           ; send out the note
  712.         ;
  713. clock2: dec     byte ptr var6[di]       ; count down note
  714.         jnz     clock2a                 ; branch if not eon
  715.         jmp     clock1b                 ; if end of note, do a new one
  716. clock2a:mov     al,0                    ; setup for note-off
  717.         mov     ah,var6[di]             ; get note clock countdown
  718.         cmp     ah,var7[di]             ; > note-off time?
  719.         jbe     clock2b                 ; no, send note off
  720.         getv    al,var5                 ; yes, send velocity    
  721. clock2b:putn    al                      ; send to output
  722. clockx: nextl                           ; exit
  723. ;==============================================================
  724. ; Loop Timer
  725. ; output: delayed pulse
  726. ; inputs: 0: strobe, 1: delay, 2: hold
  727. ;         3x: strobe clock, 4x: delay count, 4z: hold count
  728. ;--------------------------------------------------------------
  729.         public  _ltimer
  730. _ltimer:
  731.         test    byte ptr var4[di],-1    ; delay high?
  732.         jz      ltimer1                 ; no, branch
  733.         dec     byte ptr var4[di]       ; yes, count down
  734.         jnz     ltimerz                 ; exit if not finished
  735. ltimer0:mov     byte ptr outn[di],1     ; else set output
  736.         jmp     short ltimerz           ; then exit
  737.         ;
  738. ltimer1:test    byte ptr var4+1[di],-1  ; hold high?
  739.         jz      ltimer2                 ; no, branch
  740.         dec     byte ptr var4+1[di]     ; yes, count down
  741.         jnz     ltimerz                 ; exit if not finished
  742.         mov     byte ptr outn[di],0     ; else clear output
  743.         jmp     short ltimerz           ; then exit
  744.         ;
  745. ltimer2:tick    var0,var3               ; strobe tick?
  746.         jnc     ltimerz                 ; no, just exit
  747.         getv    al,var1                 ; yes, get delay
  748.         getv    ah,var2                 ; ...get hold
  749.         or      ah,mprstf               ; /
  750.         mov     var4[di],ax             ; set them up
  751.         or      al,al                   ; delay = 0?
  752.         jz      ltimer0                 ; yes, go set
  753.         mov     byte ptr outn[di],0     ; else clear output
  754. ltimerz:nextl                           ; exit
  755. ;==============================================================
  756. ; Clock Timer
  757. ; output: delayed pulse
  758. ; inputs: 0: clock, 1: strobe, 2: delay, 3: hold
  759. ;         4x: strobe clock, 5x: delay count, 5z: hold count
  760. ;--------------------------------------------------------------
  761.         public  _ctimer
  762. _ctimer:
  763.         tickb1  var1,var4               ; strobe tick?
  764.         jnc     ctimer2                 ; no, go on
  765.         getv    al,var2                 ; yes, get delay
  766.         getv    ah,var3                 ; ...get hold
  767.         or      ah,mprstf               ; /
  768.         mov     var5[di],ax             ; set them up
  769.         or      al,al                   ; delay = 0?
  770.         jz      ctimer0                 ; yes, go set
  771.         mov     byte ptr outn[di],0     ; clear output
  772.         jmp     short ctimerz           ; exit
  773.         ;
  774. ctimer2:tick    var0,var4               ; clock tick?
  775.         jnc     ctimerz                 ; no, branch
  776.         ;
  777.         test    byte ptr var5[di],-1    ; delay high?
  778.         jz      ctimer1                 ; no, branch
  779.         dec     byte ptr var5[di]       ; yes, count down
  780.         jnz     ctimerz                 ; exit if not finished
  781. ctimer0:mov     byte ptr outn[di],1     ; else set output
  782.         jmp     short ctimerz           ; then exit
  783.         ;
  784. ctimer1:test    byte ptr var5+1[di],-1  ; hold high?
  785.         jz      ctimerz                 ; no, branch
  786.         dec     byte ptr var5+1[di]     ; yes, count down
  787.         jnz     ctimerz                 ; exit if not finished
  788.         mov     byte ptr outn[di],0     ; else clear output
  789.         ;
  790. ctimerz:nextl                           ; exit
  791. ;==============================================================
  792. ; Abs Timer
  793. ; output: delayed pulse
  794. ; inputs: 0: strobe, 1: delay, 2: hold, 3: period
  795. ;         4: timer value
  796. ;         5x: b0=delay flag, b1=hold flag
  797. ;         5z: clock
  798. ;--------------------------------------------------------------
  799.         public  _atimer
  800. _atimer:
  801.         test    byte ptr var5[di],1     ; delay high?
  802.         jz      atimer1                 ; no, branch
  803.         mov     ax,cs:ticks             ; yes, get timer value
  804.         sub     ax,var4[di]             ; get lapsed time
  805.         getv    dl,var1                 ; get delay time
  806.         mov     dh,0                    ; /
  807.         getv    cl,var3                 ; get period
  808.         shl     dx,cl                   ; bump
  809.         cmp     dx,ax                   ; out of gas?
  810.         jnb     atimerz                 ; no, exit
  811.         mov     ax,cs:ticks             ; get current ticks
  812.         mov     var4[di],ax             ; save it
  813. atimer0:mov     byte ptr outn[di],1     ; set output
  814.         hold    var2                    ; hold?
  815.         jz      atimer3                 ; no, clear flag & exit
  816.         mov     byte ptr var5[di],2     ; yes, set hold flag
  817.         jmp     short atimerz           ; then exit
  818.         ;
  819. atimer1:test    byte ptr var5[di],2     ; hold high?
  820.         jz      atimer2                 ; no, branch
  821.         mov     ax,cs:ticks             ; yes, get timer value
  822.         sub     ax,var4[di]             ; get lapsed time
  823.         getv    dl,var2                 ; get hold time
  824.         mov     dh,0                    ; /
  825.         getv    cl,var3                 ; get period
  826.         shl     dx,cl                   ; bump
  827.         cmp     dx,ax                   ; out of gas?
  828.         jnb     atimerz                 ; no, exit
  829.         mov     byte ptr outn[di],0     ; ...clear output
  830. atimer3:mov     byte ptr var5[di],0     ; yes, clear flags
  831.         jmp     short atimerz           ; then exit
  832.         ;
  833. atimer2:tick    var0,var5+1             ; strobe tick?
  834.         jnc     atimerz                 ; no, just exit
  835.         mov     ax,cs:ticks             ; get current ticks
  836.         mov     var4[di],ax             ; save it
  837.         testv   var1,-1                 ; delay = 0
  838.         jz      atimer0                 ; yes, go set
  839.         mov     byte ptr var5[di],1     ; else flag delay
  840.         mov     byte ptr outn[di],0     ; ...clear output
  841. atimerz:nextl                           ; exit
  842. ;==============================================================
  843. ; Seconds Timer
  844. ; output: delayed pulse
  845. ; inputs: 0: strobe, 1: delay, 2: hold, 3: period
  846. ;         4: timer value
  847. ;         5x: b0=delay flag, b1=hold flag
  848. ;         5z: clock
  849. ;--------------------------------------------------------------
  850.         public  _stimer
  851. _stimer:
  852.         test    byte ptr var5[di],1     ; delay high?
  853.         jz      stimer1                 ; no, branch
  854.         mov     ax,cs:seconds           ; yes, get timer value
  855.         sub     ax,var4[di]             ; get lapsed time
  856.         getv    dl,var1                 ; get delay time
  857.         mov     dh,0                    ; /
  858.         getv    cl,var3                 ; get period
  859.         shl     dx,cl                   ; bump
  860.         cmp     dx,ax                   ; out of gas?
  861.         jnb     stimerz                 ; no, exit
  862.         mov     ax,cs:seconds           ; get current ticks
  863.         mov     var4[di],ax             ; save it
  864. stimer0:mov     byte ptr outn[di],1     ; set output
  865.         hold    var2                    ; hold?
  866.         jz      stimer3                 ; no, clear flag & exit
  867.         mov     byte ptr var5[di],2     ; yes, set hold flag
  868.         jmp     short stimerz           ; then exit
  869.         ;
  870. stimer1:test    byte ptr var5[di],2     ; hold high?
  871.         jz      stimer2                 ; no, branch
  872.         mov     ax,cs:seconds           ; yes, get timer value
  873.         sub     ax,var4[di]             ; get lapsed time
  874.         getv    dl,var2                 ; get hold time
  875.         mov     dh,0                    ; /
  876.         getv    cl,var3                 ; get period
  877.         shl     dx,cl                   ; bump
  878.         cmp     dx,ax                   ; out of gas?
  879.         jnb     stimerz                 ; no, exit
  880.         mov     byte ptr outn[di],0     ; ...clear output
  881. stimer3:mov     byte ptr var5[di],0     ; yes, clear flags
  882.         jmp     short stimerz           ; then exit
  883.         ;
  884. stimer2:tick    var0,var5+1             ; strobe tick?
  885.         jnc     stimerz                 ; no, just exit
  886.         mov     ax,cs:seconds           ; get current ticks
  887.         mov     var4[di],ax             ; save it
  888.         testv   var1,-1                 ; delay = 0
  889.         jz      stimer0                 ; yes, go set
  890.         mov     byte ptr var5[di],1     ; else flag delay
  891.         mov     byte ptr outn[di],0     ; ...clear output
  892. stimerz:nextl                           ; exit
  893. ;==============================================================
  894. ; interference clock
  895. ; inputs: 0:   hold/reset input
  896. ;         1-4: clock inputs
  897. ;         5x:
  898. ;         5z:  clock ticks
  899. ; output: strobe upon any clock input
  900. ;--------------------------------------------------------------
  901.         public _iclock
  902. _iclock:
  903.         hold    var0                    ; hold?
  904.         jz      iclock0                 ; no, branch
  905.         jmp     iclockz                 ; else exit
  906.         ;
  907. iclock0:tick    var1,var5+1             ; clock
  908.         jnc     iclock1                 ; branch if no tick
  909.         mov     byte ptr outn[di],1     ; else set output
  910. iclock1:
  911.         tickb1  var2,var5+1             ; clock
  912.         jnc     iclock2                 ; branch if no tick
  913.         mov     byte ptr outn[di],1     ; else set output
  914. iclock2:
  915.         tickb2  var3,var5+1             ; clock
  916.         jnc     iclock3                 ; branch if no tick
  917.         mov     byte ptr outn[di],1     ; else set output
  918. iclock3:
  919.         tickb3  var4,var5+1             ; clock
  920.         jnc     iclockz                 ; branch if no tick
  921.         mov     byte ptr outn[di],1     ; else set output
  922. iclockz:nextt                           ; exit
  923. ;==============================================================
  924. ; interference clock
  925. ; inputs: 0:   clock
  926. ;         1:   hold/reset input
  927. ;         2-5: count inputs
  928. ;         6x:
  929. ;         6z:  clock ticks
  930. ;         7-8: change detectors 
  931. ;         9-10:countdown registers    
  932. ; output: strobe upon any clock input
  933. ;--------------------------------------------------------------
  934.         public _kclock
  935. _kclock:
  936.         hold    var1                    ; hold?
  937.         jz      kclocka                 ; no, branch
  938. kclockb:mov     ax,101H                 ; yes, clear registers
  939.         mov     var9[di],ax             ;  /
  940.         mov     var10[di],ax            ; /
  941.         jmp     kclockz                 ; exit
  942.         ;
  943. kclocka:tick    var0,var6+1             ; clock
  944.         jc      kclockd                 ; do it if tick
  945.         jmp     kclockz                 ; branch if no tick
  946.         ;
  947. kclockd:getv    al,var2                 ; input change?
  948.         getv    ah,var3                 ;  /
  949.         cmp     ax,var7[di]             ; /
  950.         jz      kclockc                 ; no, branch 
  951.         mov     var7[di],ax             ; yes, reset
  952.         jmp     short kclockb           ; /
  953. kclockc:getv    al,var4                 ; input change?
  954.         getv    ah,var5                 ;  /
  955.         cmp     ax,var8[di]             ; /
  956.         jz      kclock0                 ; no, branch 
  957.         mov     var8[di],ax             ; yes, reset
  958.         jmp     short kclockb           ; /
  959.         ;
  960. kclock0:test    byte ptr var9[di],-1    ; register zero'd?
  961.         jz      kclock1                 ; yes, branch
  962.         dec     byte ptr var9[di]       ; no, count down
  963.         jnz     kclock1                 ; branch if not zero'd
  964.         getv    al,var2                 ; else get count
  965.         mov     byte ptr var9[di],al    ; reset register
  966.         mov     byte ptr outn[di],1     ; set output strobe
  967.         ;
  968. kclock1:test    byte ptr var9+1[di],-1  ; register zero'd?
  969.         jz      kclock2                 ; yes, branch
  970.         dec     byte ptr var9+1[di]     ; no, count down
  971.         jnz     kclock2                 ; branch if not zero'd
  972.         getv    al,var3                 ; else get count
  973.         mov     byte ptr var9+1[di],al  ; reset register
  974.         mov     byte ptr outn[di],1     ; set output strobe
  975.         ;
  976. kclock2:test    byte ptr var10[di],-1   ; register zero'd?
  977.         jz      kclock3                 ; yes, branch
  978.         dec     byte ptr var10[di]      ; no, count down
  979.         jnz     kclock3                 ; branch if not zero'd
  980.         getv    al,var4                 ; else get count
  981.         mov     byte ptr var10[di],al   ; reset register
  982.         mov     byte ptr outn[di],1     ; set output strobe
  983.         ;
  984. kclock3:test    byte ptr var10+1[di],-1 ; register zero'd?
  985.         jz      kclockz                 ; yes, branch
  986.         dec     byte ptr var10+1[di]    ; no, count down
  987.         jnz     kclockz                 ; branch if not zero'd
  988.         getv    al,var5                 ; else get count
  989.         mov     byte ptr var10+1[di],al ; reset register
  990.         mov     byte ptr outn[di],1     ; set output strobe
  991.         ;
  992. kclockz:nextt                           ; exit
  993. ;==============================================================
  994. ; Index counter, incrementing
  995. ; inputs: 0: clock up, 1: hold/reset 2: inc/dec 3x: tick flag
  996. ; output: index
  997. ;--------------------------------------------------------------
  998.         public _icount
  999. _icount:
  1000.         hold    var1            ; hold?
  1001.         jz      icount0         ; branch if no hold
  1002.         mov     word ptr outn[di],100h; else zip output/index  
  1003.         jmp     short icountx   ; exit with video update
  1004. icount0:tick    var0,var3       ; clock tick
  1005.         jc      icount1         ; branch if there is a tick
  1006.         nextx                   ; else exit easy
  1007. icount1:testv   var2,-1         ; test inc/dec flag
  1008.         jnz     icount2         ; branch if decrement
  1009.         inc     word ptr outn[di]; inc index
  1010.         jmp     next            ; exit with video update
  1011. icount2:dec     word ptr outn[di]; dec index
  1012. icountx:nextv                   ; exit
  1013. ;==============================================================
  1014. ; Index counter, with mask
  1015. ; inputs: 0: clock up,   1: hold/reset 2: mask
  1016. ;         3x: tick flag, 3z: tick count     
  1017. ; output: index
  1018. ;--------------------------------------------------------------
  1019.         public _ocount
  1020. _ocount:
  1021.         hold    var1            ; hold?
  1022.         jz      ocount0         ; branch if no hold
  1023.         mov     byte ptr var3+1[di],0; else zip index  
  1024.         jmp     short ocountx   ; exit with video update
  1025. ocount0:tick    var0,var3       ; clock tick
  1026.         jnc     ocountx         ; branch if no tick
  1027.         inc     byte ptr var3+1[di]; inc index
  1028. ocountx:getv    al,var2         ; get the mask
  1029.         and     al,var3+1[di]   ; and with count
  1030.         putn    al              ; send it out
  1031.         nextv                   ; exit
  1032. ;==============================================================
  1033. ; Index counter, adding
  1034. ; inputs: 0: clock up, 1: hold/reset 2: increment 3x: tick flag
  1035. ; output: index
  1036. ;--------------------------------------------------------------
  1037.         public _jcount
  1038. _jcount:
  1039.         hold    var1            ; hold?
  1040.         jz      jcount0         ; branch if no hold
  1041.         mov     word ptr outn[di],100H; else zip output/index  
  1042. jcountx:jmp     next            ; exit
  1043. jcount0:tick    var0,var3       ; clock tick
  1044.         jc      jcount1         ; branch if there is a tick
  1045.         nextx                   ; else exit easy
  1046. jcount1:getv    al,var2         ; get the increment
  1047.         add     outn[di],al     ; add to the index
  1048.         nextv                   ; exit with video update
  1049. ;==============================================================
  1050. ; Index counter, adding with upper limit
  1051. ; inputs: 0: clock up, 1: hold/reset 2: increment 
  1052. ;         3: inc/dec   4: top limit  5x: tick
  1053. ; output: index
  1054. ;--------------------------------------------------------------
  1055.         public _kcount
  1056. _kcount:
  1057.         hold    var1            ; hold?
  1058.         jz      kcount0         ; branch if no hold
  1059.         testv   var3,-1         ; counting up or down
  1060.         jnz     kcounta         ; branch if counting down
  1061.         mov     al,0            ; up, set to bottom limit
  1062.         jmp     short kcountb   ; /
  1063. kcounta:getv    al,var4         ; down, set to top limit
  1064. kcountb:mov     ah,al           ;   /
  1065.         mov     outn[di],ax     ; /
  1066.         jmp     next            ; exit
  1067. kcount0:tick    var0,var5       ; clock tick
  1068.         jc      kcount1         ; branch if there is a tick
  1069.         nextx                   ; else exit easy
  1070. kcount1:mov     dl,0            ; dl = 0 = bottom
  1071.         getv    dh,var4         ; dh = the top limit
  1072.         jmp     lcountk         ; continue with lcount routine
  1073. ;==============================================================
  1074. ; Index counter, adding with upper and lower limit
  1075. ; inputs: 0: clock up, 1: hold/reset 2: increment 
  1076. ;         3: inc/dec   4: top limit  5: bottom limit 
  1077. ;         6x: tick
  1078. ; output: index                 
  1079. ;--------------------------------------------------------------
  1080.         public _lcount
  1081. _lcount:
  1082.         hold    var1            ; hold?
  1083.         jz      lcount0         ; branch if no hold
  1084.         testv   var3,-1         ; counting up or down
  1085.         jnz     lcounta         ; branch if counting down
  1086.         getv    al,var5         ; up, set to bottom limit
  1087.         jmp     short lcountb   ; /
  1088. lcounta:getv    al,var4         ; down, set to top limit
  1089. lcountb:mov     ah,al           ;   /
  1090.         mov     outn[di],ax     ; /
  1091.         jmp     next            ; exit
  1092. lcount0:tick    var0,var6       ; clock tick
  1093.         jc      lcount1         ; branch if there is a tick
  1094.         nextx                   ; else exit easy
  1095. lcount1:getv    dl,var5         ; dl = the lower limit
  1096.         getv    dh,var4         ; dh = the top limit
  1097.         cmp     dh,dl           ; top < bottom ?
  1098.         jnb     lcountk         ; no, branch
  1099.         xchg    dh,dl           ; yes, swap
  1100. lcountk:inc     dh              ; bump so top is included
  1101.         getv    al,var2         ; al = the increment
  1102.         getv    ah,var3         ; ah = inc/dec
  1103.         test    ah,-1           ; inc or dec?
  1104.         jnz     lcount2         ; branch if dec
  1105.         ;                       ; counting up
  1106.         add     al,outn+1[di]   ; add inc to index
  1107.         cmp     al,dh           ; over the top?
  1108.         jna     lcount3         ; no, branch
  1109.         sub     al,dh           ; yes, subtract top
  1110.         add     al,dl           ; add bottom
  1111. lcount3:mov     ah,al           ; set new index
  1112.         dec     al              ; show index -1
  1113.         mov     outn[di],ax     ; /
  1114.         jmp     next            ; display & exit
  1115.         ;                       ; counting down
  1116. lcount2:mov     cl,outn+1[di]   ; get index
  1117.         sub     cl,al           ; subtract inc
  1118.         jc      lcount5         ; branch if rollover
  1119.         cmp     cl,dl           ; below the limit
  1120.         jnb     lcount4         ; no, branch
  1121. lcount5:add     cl,dh           ; yes, add top
  1122.         sub     cl,dl           ; subtract bottom
  1123. lcount4:mov     ch,cl           ; set new index
  1124.         mov     outn[di],cx     ; /
  1125.         jmp     next            ; display & exit
  1126.  
  1127. ;==============================================================
  1128. ; Index counter, adding with upper and lower limit
  1129. ; inputs: 0: clock up, 1: hold/reset 2: increment 
  1130. ;         3: inc/dec   4: top limit  5: bottom limit 
  1131. ;         6x: tick
  1132. ; output: index                 
  1133. ;--------------------------------------------------------------
  1134.         public _mcount
  1135. _mcount:
  1136.         hold    var1            ; hold?
  1137.         jz      mcount0         ; branch if no hold
  1138.         testv   var3,-1         ; counting up or down
  1139.         jnz     mcounta         ; branch if counting down
  1140.         getv    al,var5         ; up, set to bottom limit
  1141.         jmp     short mcountb   ; /
  1142. mcounta:getv    al,var4         ; down, set to top limit
  1143. mcountb:mov     ah,al           ;  /
  1144.         mov     outn[di],ax     ; /
  1145.         jmp     next            ; exit
  1146. mcount0:tick    var0,var6       ; clock tick
  1147.         jc      mcount1         ; branch if there is a tick
  1148.         nextx                   ; else exit easy
  1149. mcount1:getv    dl,var5         ; dl = the lower limit
  1150.         getv    dh,var4         ; dh = the top limit
  1151.         cmp     dh,dl           ; top < bottom ?
  1152.         jnb     mcountk         ; no, branch
  1153.         xchg    dh,dl           ; yes, swap
  1154. mcountk:inc     dh              ; bump so top is included
  1155.         getv    al,var2         ; al = the increment
  1156.         getv    ah,var3         ; ah = inc/dec
  1157.         test    ah,-1           ; inc or dec?
  1158.         jnz     mcount2         ; branch if dec
  1159.         ;                       ; counting up
  1160.         add     al,outn+1[di]   ; add inc to index
  1161.         cmp     al,dh           ; over the top?
  1162.         jna     mcount3         ; no, branch
  1163.         mov     al,dh           ; get hi count
  1164.         sub     al,dl           ; get hi-lo
  1165.         shr     al,1            ; /2
  1166.         mov     ah,al           ; hold
  1167.         shr     al,1            ; 1/4
  1168.         add     al,ah           ; 3/4
  1169.         add     al,dl           ; offset from bottom
  1170. mcount3:mov     ah,al           ; set new index
  1171.         mov     outn[di],ax     ; /
  1172.         jmp     next            ; display & exit
  1173.         ;                       ; counting down
  1174. mcount2:mov     cl,outn+1[di]   ; get index
  1175.         sub     cl,al           ; subtract inc
  1176.         jc      mcount5         ; branch if rollover
  1177.         cmp     cl,dl           ; below the limit
  1178.         jnb     mcount4         ; no, branch
  1179. mcount5:mov     cl,dh           ; get hi count
  1180.         sub     cl,dl           ; get hi-lo
  1181.         shr     cl,1            ; 1/2
  1182.         shr     cl,1            ; 1/4
  1183.         add     cl,dl           ; offset from bottom
  1184. mcount4:mov     ch,cl           ; set new index
  1185.         mov     outn[di],cx     ; /
  1186.         jmp     next            ; display & exit
  1187.  
  1188. ;==============================================================
  1189. ; Index counter, incrementing, 16 bit
  1190. ; inputs: 0: clock up
  1191. ;         1: hold/reset
  1192. ;         2: reset count lo
  1193. ;         3: reset count hi
  1194. ;         4: reset
  1195. ;         5: shift output
  1196. ;         6: up/down
  1197. ;         7x:tick flag
  1198. ;         8: index
  1199. ; output: index
  1200. ;--------------------------------------------------------------
  1201.         public _ncount
  1202. _ncount:
  1203.         testv   var4,-1                 ; reset?
  1204.         jz      ncount0                 ; no, branch
  1205.         getv    al,var2                 ; yes, get reset count lo
  1206.         getv    ah,var3                 ; ... and reset count hi
  1207.         mov     var8[di],ax             ; reset
  1208.         ;
  1209. ncount0:hold    var1                    ; hold?
  1210.         jnz     ncountx                 ; branch if no hold
  1211.         ;
  1212.         tick    var0,var7               ; clock tick
  1213.         jnc     ncountx                 ; branch if no tick
  1214.         mov     ax,1                    ; setup for inc
  1215.         testv   var6,-1                 ; up or down
  1216.         jz      ncount1                 ; branch if up
  1217.         mov     ax,-1                   ; else setup for down
  1218. ncount1:
  1219.         add     var8[di],ax             ; bump index
  1220.         ;
  1221. ncountx:mov     ax,word ptr var8[di]    ; get the index
  1222.         getv    cl,var5                 ; get shift byte
  1223.         shr     ax,cl                   ; bump right
  1224.         putn    al                      ; send it out
  1225.         nextv                           ; exit
  1226. ;==============================================================
  1227. ; Sequencer/Switcher
  1228. ; inputs: 0: stage addr, 1 - 16: stages, xl: old stage
  1229. ; output: value of stage pointed to by var0
  1230. ;
  1231.         public _wseq
  1232. _wseq:  
  1233.         getv    al,var0         ; get variable0
  1234.         and     al,15           ; 16 stages
  1235.         mov     cl,al           ; save it
  1236.         mov     ch,var1+32[di]  ; get saved last stage
  1237.         and     ch,15           ; just to be safe
  1238.         mov     var1+32[di],al  ; store the new stage
  1239.         mov     ah,0            ; make new stage into word
  1240.         add     ax,ax           ; /
  1241.         mov     bx,ax           ; bx = offset to the stage
  1242.         mov     bx,var1[bx+di]  ; get the value
  1243.         mov     al,[bx]         ; /
  1244.         putn    al              ; send to output
  1245. ;--------------------------------------------------------------
  1246. ; got the value, now clear old stage led, and set the new
  1247. ;--------------------------------------------------------------
  1248.         cmp     cl,ch           ; have stages changed?
  1249.         jz      wseqx           ; no, then just exit
  1250.         gettag                  ; es:bx = screen addr of tag
  1251.         dec     bx              ; point to leds
  1252.         add     ch,4            ; offset to 2nd var loc in screen
  1253.         mov     al,160          ; point to stage led
  1254.         mul     ch              ; ax = offset to old stage led
  1255.         mov     di,ax           ; put in di for indexing
  1256.         mov     byte ptr es:[bx+di],yellow; turn the led off
  1257.         add     cl,4            ; offset to 2nd var loc in screen
  1258.         mov     al,160          ; point to stage led
  1259.         mul     cl              ; ax = offset to new stage led
  1260.         mov     di,ax           ; put in di for indexing
  1261.         mov     byte ptr es:[bx+di],hi+red; turn the led on 
  1262. wseqx:
  1263.         mov     di,2[si]        ;; set di pointing to variable list
  1264.         nextv                   ; show the output
  1265. ;==============================================================
  1266. ; Sequencer/Switcher
  1267. ; inputs: 0: stage addr, 1 - 8: stages, xl: old stage
  1268. ; output: value of stage pointed to by var0
  1269. ;
  1270.         public _xseq
  1271. _xseq:  
  1272.         getv    al,var0         ; get variable0
  1273.         and     al,7            ; 8  stages
  1274.         mov     cl,al           ; save it
  1275.         mov     ch,var1+16[di]  ; get saved last stage
  1276.         and     ch,7            ; just to be safe
  1277.         mov     var1+16[di],al  ; store the new stage
  1278.         mov     ah,0            ; make new stage into word
  1279.         add     ax,ax           ; /
  1280.         mov     bx,ax           ; bx = offset to the stage
  1281.         mov     bx,var1[bx+di]  ; get the value
  1282.         mov     al,[bx]         ; /
  1283.         putn    al              ; send to output
  1284. ;--------------------------------------------------------------
  1285. ; got the value, now clear old stage led, and set the new
  1286. ;--------------------------------------------------------------
  1287.         cmp     cl,ch           ; have stages changed?
  1288.         jz      xseqx           ; no, then just exit
  1289.         gettag                  ; es:bx = screen addr of tag
  1290.         dec     bx              ; point to leds
  1291.         add     ch,4            ; offset to 2nd var loc in screen
  1292.         mov     al,160          ; point to stage led
  1293.         mul     ch              ; ax = offset to old stage led
  1294.         mov     di,ax           ; put in di for indexing
  1295.         mov     byte ptr es:[bx+di],yellow; turn the led off
  1296.         add     cl,4            ; offset to 2nd var loc in screen
  1297.         mov     al,160          ; point to stage led
  1298.         mul     cl              ; ax = offset to new stage led
  1299.         mov     di,ax           ; put in di for indexing
  1300.         mov     byte ptr es:[bx+di],hi+red; turn the led on 
  1301. xseqx:
  1302.         mov     di,2[si]        ; set di pointing to variable list
  1303.         nextv                   ; show the output
  1304. ;==============================================================
  1305. ; Sequencer/Switcher
  1306. ; inputs: 0: stage addr, 1 - 4: stages, xl: old stage
  1307. ; output: value of stage pointed to by var0
  1308. ;
  1309.         public _yseq
  1310. _yseq:  
  1311.         getv    al,var0         ; get variable0
  1312.         and     al,3            ;  4 stages
  1313.         mov     cl,al           ; save it
  1314.         mov     ch,var1+8[di]   ; get saved last stage
  1315.         and     ch,3            ; just to be safe
  1316.         mov     var1+8[di],al   ; store the new stage
  1317.         mov     ah,0            ; make new stage into word
  1318.         add     ax,ax           ; /
  1319.         mov     bx,ax           ; bx = offset to the stage
  1320.         mov     bx,var1[bx+di]  ; get the value
  1321.         mov     al,[bx]         ; /
  1322.         putn    al              ; send to output
  1323. ;--------------------------------------------------------------
  1324. ; got the value, now clear old stage led, and set the new
  1325. ;--------------------------------------------------------------
  1326.         cmp     cl,ch           ; have stages changed?
  1327.         jz      yseqx           ; no, then just exit
  1328.         gettag                  ; es:bx = screen addr of tag
  1329.         dec     bx              ; point to leds
  1330.         add     ch,4            ; offset to 2nd var loc in screen
  1331.         mov     al,160          ; point to stage led
  1332.         mul     ch              ; ax = offset to old stage led
  1333.         mov     di,ax           ; put in di for indexing
  1334.         mov     byte ptr es:[bx+di],yellow; turn the led off
  1335.         add     cl,4            ; offset to 2nd var loc in screen
  1336.         mov     al,160          ; point to stage led
  1337.         mul     cl              ; ax = offset to new stage led
  1338.         mov     di,ax           ; put in di for indexing
  1339.         mov     byte ptr es:[bx+di],hi+red; turn the led on 
  1340. yseqx:
  1341.         mov     di,2[si]        ; set di pointing to variable list
  1342.         nextv                   ; show the output
  1343. ;==============================================================
  1344. ; Sequencer/Switcher
  1345. ; inputs: 0: stage addr, 1 - 2: stages, xl: old stage
  1346. ; output: value of stage pointed to by var0
  1347. ;
  1348.         public _zseq
  1349. _zseq:  
  1350.         getv    al,var0         ; get variable0
  1351.         and     al,1            ;  1 stages
  1352.         mov     cl,al           ; save it
  1353.         mov     ch,var1+4[di]   ; get saved last stage
  1354.         and     ch,1            ; just to be safe
  1355.         mov     var1+4[di],al   ; store the new stage
  1356.         mov     ah,0            ; make new stage into word
  1357.         add     ax,ax           ; /
  1358.         mov     bx,ax           ; bx = offset to the stage
  1359.         mov     bx,var1[bx+di]  ; get the value
  1360.         mov     al,[bx]         ; /
  1361.         putn    al              ; send to output
  1362. ;--------------------------------------------------------------
  1363. ; got the value, now clear old stage led, and set the new
  1364. ;--------------------------------------------------------------
  1365.         cmp     cl,ch           ; have stages changed?
  1366.         jz      zseqx           ; no, then just exit
  1367.         gettag                  ; es:bx = screen addr of tag
  1368.         dec     bx              ; point to leds
  1369.         add     ch,4            ; offset to 2nd var loc in screen
  1370.         mov     al,160          ; point to stage led
  1371.         mul     ch              ; ax = offset to old stage led
  1372.         mov     di,ax           ; put in di for indexing
  1373.         mov     byte ptr es:[bx+di],yellow; turn the led off
  1374.         add     cl,4            ; offset to 2nd var loc in screen
  1375.         mov     al,160          ; point to stage led
  1376.         mul     cl              ; ax = offset to new stage led
  1377.         mov     di,ax           ; put in di for indexing
  1378.         mov     byte ptr es:[bx+di],hi+red; turn the led on 
  1379. zseqx:
  1380.         mov     di,2[si]        ; set di pointing to variable list
  1381.         nextv                   ; show the output
  1382. ;==============================================================
  1383. ; Sequencer/Switcher
  1384. ; output: "a" input if var0 AND var1 = 0, else "b" input
  1385. ; inputs: 
  1386. ; 0, 1: test inputs, ANDed to give flag
  1387. ; 2: input stage "a"
  1388. ; 3: input stage "b"
  1389. ;
  1390.         public _useq
  1391. _useq:  getv    dl,var0         ; get flag vars
  1392.         getv    dh,var1         ; /
  1393.         mov     ch,yellow       ; set up led colors
  1394.         mov     cl,red+hi       ; /
  1395.         getv    al,var2         ; get "a" input
  1396.         ;
  1397.         and     dh,dl           ; test
  1398.         jz      useq0           ; branch if "b" input
  1399.         xchg    ch,cl           ; else setup for 2nd
  1400.         getv    al,var3         ; get "b" input
  1401.         ;
  1402. useq0:  gettag                  ; get screen address of leds
  1403.         add     bx,799          ; set up input leds
  1404.         mov     es:[bx],cl      ; do the leds
  1405.         mov     es:160[bx],ch   ; /
  1406.         ;
  1407.         putn    al              ; send to output
  1408.         nextv                   ; exit        
  1409. ;==============================================================
  1410. ; Sequencer/Switcher
  1411. ; output: "a" input if var0 AND var1 = 0, else "b" input
  1412. ; inputs: 
  1413. ; 0, 1: test inputs, ANDed to give flag
  1414. ; 2: input stage "a"
  1415. ; 3: input stage "b"
  1416. ; 4: offset
  1417. ;
  1418.         public _vseq
  1419. _vseq:  getv    dl,var0         ; get flag vars
  1420.         getv    dh,var1         ; /
  1421.         mov     ch,yellow       ; set up led colors
  1422.         mov     cl,red+hi       ; /
  1423.         getv    al,var2         ; get "a" input
  1424.         ;
  1425.         and     dh,dl           ; test
  1426.         jz      vseq0           ; branch if "b" input
  1427.         xchg    ch,cl           ; else setup for 2nd
  1428.         getv    al,var3         ; get "b" input
  1429.         ;
  1430. vseq0:  gettag                  ; get screen address of leds
  1431.         add     bx,799          ; set up input leds
  1432.         mov     es:[bx],cl      ; do the leds
  1433.         mov     es:160[bx],ch   ; /
  1434.         ;
  1435.         getv    ah,var4         ; get the offset
  1436.         add     al,ah           ; put them together
  1437.         putn    al              ; send to output
  1438.         nextv                   ; exit        
  1439. ;==============================================================
  1440. ; Pass input thru to output on nz test input, zero on low
  1441. ; inputs: 0: switch 
  1442. ;         1: value1, 2: value2
  1443. ; output: value/0
  1444. ;--------------------------------------------------------------
  1445.         public _passt
  1446. _passt: getv    al,var1         ; al = input a
  1447.         mov     ch,yellow       ; set up led colors
  1448.         mov     cl,red+hi       ; /
  1449.         testv   var0,-1         ; test a/b switch
  1450.         jz      passt1          ; branch if 1st input
  1451.         ;
  1452.         getv    al,var2         ; al = input b
  1453.         xchg    ch,cl           ; else setup for 2nd
  1454.         ;
  1455. passt1: putn    al              ; put it away
  1456.         ;
  1457.         gettag                  ; get screen address of leds
  1458.         dec     bx              ; /
  1459.         mov     bp,bx           ; save it
  1460.         add     bx,640          ; bx = screen addr of 1st led
  1461.         mov     es:[bx],cl      ; do the leds
  1462.         mov     es:160[bx],ch   ; /
  1463.         ;
  1464.         nextv                   ; show it
  1465. ;==============================================================
  1466. ; Pass input thru to output on nz test input, zero on low
  1467. ; inputs: 0: switch 
  1468. ;         1: value1, 2: value2, 3: offset
  1469. ; output: value/0
  1470. ;--------------------------------------------------------------
  1471.         public _passq
  1472. _passq: getv    al,var1         ; al = input a
  1473.         mov     ch,yellow       ; set up led colors
  1474.         mov     cl,red+hi       ; /
  1475.         testv   var0,-1         ; test a/b switch
  1476.         jz      passq1          ; branch if 1st input
  1477.         ;
  1478.         getv    al,var2         ; al = input b
  1479.         xchg    ch,cl           ; else setup for 2nd
  1480.         ;
  1481. passq1: getv    ah,var3         ; get offset
  1482.         add     al,ah           ; /
  1483.         putn    al              ; put it away
  1484.         ;
  1485.         gettag                  ; get screen address of leds
  1486.         dec     bx              ; /
  1487.         mov     bp,bx           ; save it
  1488.         add     bx,640          ; bx = screen addr of 1st led
  1489.         mov     es:[bx],cl      ; do the leds
  1490.         mov     es:160[bx],ch   ; /
  1491.         ;
  1492.         nextv                   ; show it
  1493. ;==============================================================
  1494. ; Standard 256 byte sequencer with input mask
  1495. ; inputs: 0: address 1: write enable, 2: input, 3: input mask 
  1496. ;         4x: module number, 4z, init flag
  1497. ; output: byte addressed by address
  1498. ;--------------------------------------------------------------
  1499.         public _pseq
  1500. _pseq:  cmp     byte ptr var4+1[di],0abh; initialized?
  1501.         jnz     pseq2           ; no, branch
  1502.         test    usrflg,1        ; user input
  1503.         jnz     pseq1           ; yes, no go
  1504.         ;
  1505.         mov     ax,seg bufsp    ; setup seg register
  1506.         mov     es,ax           ; es = seg addr
  1507.         getv    dl,var0         ; get address
  1508.         mov     dh,0            ; /
  1509.         mov     bh,var4[di]     ; get hi address
  1510.         mov     bl,0            ; /
  1511.         add     bx,dx           ; set up as index
  1512.         mov     dx,bx           ; save
  1513.         mov     al,es:[bx]      ; get the byte
  1514.         putn    al              ; send it out
  1515.         ;
  1516.         testv   var1,-1         ; write enabled?
  1517.         jz      pseq1           ; no, branch
  1518.         getv    al,var2         ; yes, get input
  1519.         getv    ah,var3         ; get mask
  1520.         and     al,ah           ; mask the input
  1521.         not     ah              ; complement
  1522.         mov     bx,dx           ; get address again
  1523.         and     es:[bx],ah      ; clear old bits
  1524.         or      es:[bx],al      ; put in new bits
  1525. ;       or      _mpab,8         ; set buffer used flag
  1526. pseq1:  nextv                   ; exit with video update
  1527.         ;
  1528. pseq2:  mov     al,modnum               ; get module number
  1529.         mov     var4[di],al             ; save it
  1530.         mov     byte ptr var4+1[di],0abh; set init flag
  1531.         initv   var3,0ffh               ; mask <- FF
  1532.         gettag                          ; es:bx = screen addr of tag
  1533.         tohex                           ; convert to hex
  1534.         mov     es:-2[bx],al            ; show the default number
  1535.         nextx                           ; exit
  1536. ;--------------------------------------------------------------
  1537. ; magenta input
  1538. ;
  1539.         public  upseq 
  1540. upseq:  pop     ax              ; stack bullshit
  1541.         mov     cmdflg,10       ; set up special routine
  1542.         mov     special,offset upseqx
  1543.         mov     di,varsav       ; point to variable list
  1544.         mov     al,outn[di]     ; get the output value
  1545.         mov     var4[di],al     ; save
  1546.         jmp     workx           ; on to the next stage
  1547.         ;
  1548. upseqx: mov     di,varsav       ; point to variable list
  1549.         mov     al,outn[di]     ; get the new channel
  1550.         xchg    var4[di],al     ; set it, get orig patch
  1551.         mov     outn[di],al     ; restore
  1552.         jmp     _cancel         ; exit
  1553. ;==============================================================
  1554. ; Standard 256 byte sequencer with offset
  1555. ; inputs: 0: address, 1: offset, 2x: mod #, 2z: init flag
  1556. ; output: byte addressed by address
  1557. ;--------------------------------------------------------------
  1558.         public _qseq,_rseq,_sseq,_tseq
  1559. _tseq:  nop
  1560. _sseq:  nop
  1561. _rseq:  nop
  1562. _qseq:  cmp     byte ptr var2+1[di],0abh; initialized?
  1563.         jnz     qseq1           ; no, branch
  1564.         test    usrflg,1        ; user input
  1565.         jnz     qseq0           ; yes, no go
  1566.         ;
  1567.         mov     ax,seg bufsp    ; setup seg register
  1568.         mov     es,ax           ; es = seg addr
  1569.         getv    dl,var1         ; get offset 
  1570.         mov     dh,0            ; (not needed)
  1571.         getv    bl,var0         ; get address
  1572.         mov     bh,var2[di]     ; get hi address
  1573.         add     bl,dl           ; set up as index
  1574.         mov     al,es:[bx]      ; get the byte
  1575.         putn    al              ; send it out
  1576. qseq0:  nextv                   ; exit with video update
  1577.         ;
  1578. qseq1:  mov     al,modnum               ; get module number
  1579.         mov     var2[di],al             ; save it
  1580.         mov     byte ptr var2+1[di],0abh; set init flag
  1581.         gettag                          ; es:bx = screen addr of tag
  1582.         tohex                           ; convert to hex
  1583.         mov     es:-2[bx],al            ; show the default number
  1584.         nextx                           ; exit
  1585. ;--------------------------------------------------------------
  1586. ; magenta input
  1587. ;
  1588.         public  uqseq 
  1589. uqseq:  pop     ax              ; stack bullshit
  1590.         mov     cmdflg,10       ; set up special routine
  1591.         mov     special,offset uqseqx
  1592.         mov     di,varsav       ; point to variable list
  1593.         mov     al,outn[di]     ; get the output value
  1594.         mov     var2[di],al     ; save
  1595.         jmp     workx           ; on to the next stage
  1596.         ;
  1597. uqseqx: mov     di,varsav       ; point to variable list
  1598.         mov     al,outn[di]     ; get the new channel
  1599.         xchg    var2[di],al     ; set it, get orig patch
  1600.         mov     outn[di],al     ; restore
  1601.         jmp     _cancel         ; exit
  1602. ;==============================================================
  1603. ; 65K byte Sequencer with input mask
  1604. ; inputs: 0: address lo, 1: address hi,  
  1605. ;       2: write enable, 3: input, 4: input mask, 5x: init flag
  1606. ; output: byte addressed by address + offset
  1607. ;--------------------------------------------------------------
  1608.         public _puseq
  1609. _puseq: 
  1610.         cmp     byte ptr var5[di],0abh; initialized?
  1611.         jnz     puseq2          ; no, branch
  1612.         mov     ax,seg buffs    ; setup seg register
  1613.         mov     es,ax           ; es = seg addr
  1614.         getv    dl,var0         ; get address lo
  1615.         getv    dh,var1         ; get address hi
  1616.         mov     bx,dx           ; set up as index
  1617.         mov     al,es:[bx]      ; get the byte
  1618.         putn    al              ; send it out
  1619.         ;
  1620.         testv   var2,-1         ; write enabled?
  1621.         jz      puseq1          ; no, branch
  1622.         getv    al,var3         ; yes, get input
  1623.         getv    ah,var4         ; get mask
  1624.         and     al,ah           ; mask the input
  1625.         not     ah              ; complement
  1626.         mov     bx,dx           ; get address again
  1627.         and     es:[bx],ah      ; clear old bits
  1628.         or      es:[bx],al      ; put in new bits
  1629. ;       or      _mpab,4         ; set buffer used flag
  1630. puseq1: nextv                   ; exit with video update
  1631.         ;
  1632. puseq2: mov     al,modnum               ; get module number
  1633.         mov     byte ptr var5[di],0abh; set init flag
  1634.         initv   var4,0ffh               ; mask <- FF
  1635.         nextx                           ; exit
  1636. ;==============================================================
  1637. ; 65K byte sequencer with offset
  1638. ; inputs: 0: address lo, 1: address hi, 2: offset
  1639. ; output: byte addressed by address
  1640. ;--------------------------------------------------------------
  1641.  
  1642.         public _quseq,_ruseq,_suseq,_tuseq
  1643. _tuseq: nop
  1644. _suseq: nop
  1645. _ruseq: nop
  1646. _quseq: 
  1647.         mov     ax,seg buffs    ; setup seg register
  1648.         mov     es,ax           ; es = seg addr
  1649.         getv    dl,var0         ; get address lo
  1650.         getv    dh,var1         ; get address hi
  1651.         getv    bl,var2         ; get offset
  1652.         mov     bh,0            ; /
  1653.         add     bx,dx           ; set up as index
  1654.         mov     al,es:[bx]      ; get the byte
  1655.         putn    al              ; send it out
  1656.         nextv                   ; exit with video update
  1657. ;==============================================================
  1658. ; Delay Sequencer
  1659.  
  1660. ; inputs: 0: clock, 1: page address, 2: read offset, 3: write enable,
  1661. ;         4: input, 5: offset,  6x: clock tick  
  1662.  
  1663. ; inputs: 0: clock
  1664. ;         1: input
  1665. ;         2: read offset
  1666. ;         3: write enable
  1667. ;         4: offset
  1668. ;         5x: page address
  1669. ;         5z: index
  1670. ;         6x: clock tick
  1671. ;         6z: init flag  
  1672. ; output: byte addressed by index (hi byte of output addr) + var2
  1673. ;         AND 15 + (var1 * 16), AFTER write operation.
  1674. ; Thus, a read offset of 0 causes the output to track the input,
  1675. ; an offset of 1 tracks 1 clock behind, etc.
  1676. ;--------------------------------------------------------------
  1677.         public _euseq
  1678. _euseq: 
  1679.         cmp     byte ptr var6+1[di],0abh; initialized?
  1680.         jnz     euseqi          ; no, go do it 
  1681.         ;
  1682.         tick    var0,var6       ; clock tick
  1683.         jnc     euseqx          ; exit if no tick
  1684.         ;
  1685.         mov     ax,seg buftu    ; setup seg register
  1686.         mov     cl,var5[di]     ; ch = buffer page addr low
  1687.         mov     ch,0            ; cx = buffer page addr
  1688.         add     ax,cx           ; ax = seg addr of 16 byte buffer
  1689.         mov     es,ax           ; es = seg addr
  1690.         mov     ah,var5+1[di]   ; ah = index offset
  1691.         ;
  1692.         testv   var3,-1         ; write enabled?
  1693.         jz      euseq2          ; no, branch
  1694.         getv    al,var1         ; yes, get input
  1695.         mov     bl,ah           ; set up offset
  1696.         and     bl,15           ; 15 bytes in the buffer
  1697.         mov     bh,0            ; /
  1698.         mov     es:[bx],al      ; write the byte
  1699.         ;
  1700. euseq2: getv    al,var2         ; al = read offset
  1701.         neg     al              ; read behind
  1702.         add     al,ah           ; al = index-offset
  1703.         and     al,15           ; 15 bytes in the buffer
  1704.         mov     bl,al           ; set up an index pointer
  1705.         mov     bh,0            ; /
  1706.         mov     al,es:[bx]      ; get the read byte
  1707.         getv    dl,var4         ; get offset
  1708.         add     al,dl           ; add to output
  1709.         putn    al              ; send it out
  1710.         ;
  1711.         inc     ah              ; bump index
  1712.         mov     var5+1[di],ah   ; set the new index
  1713.         nextv                   ; exit with video update
  1714. euseqx: nextx
  1715. ;
  1716. euseqi: mov     byte ptr var6+1[di],0abh; set init flag
  1717.         initv   var3,1                  ; write enable
  1718.         mov     al,modnum               ; get module number
  1719.         mov     ah,0                    ; zip index
  1720.         mov     var5[di],ax             ; save it
  1721.         gettag                          ; es:bx = screen addr of tag
  1722.         tohex                           ; convert to hex
  1723.         mov     es:-2[bx],al            ; show the default number
  1724.         nextx                           ; exit
  1725. ;--------------------------------------------------------------
  1726. ; magenta input
  1727. ;
  1728.         public  ueuseq 
  1729. ueuseq: pop     ax              ; stack bullshit
  1730.         mov     cmdflg,10       ; set up special routine
  1731.         mov     special,offset ueuseqx
  1732.         mov     di,varsav       ; point to variable list
  1733.         mov     al,outn[di]     ; get the output value
  1734.         mov     var5[di],al     ; save
  1735.         jmp     workx           ; on to the next stage
  1736.         ;
  1737. ueuseqx:mov     di,varsav       ; point to variable list
  1738.         mov     al,outn[di]     ; get the new channel
  1739.         xchg    var5[di],al     ; set it, get orig patch
  1740.         mov     outn[di],al     ; restore
  1741.         jmp     _cancel         ; exit
  1742. ;==============================================================
  1743. ; set/clear mute flags
  1744. ; inputs: 0: flags 0-7,  1: flags 8-15,
  1745. ;         2: shift, 3: mask
  1746. ;         4x: last var0, 4z: last var1 
  1747. ;
  1748. ; output: 16bit mute word, shifted & masked
  1749. ;--------------------------------------------------------------
  1750.         public  _domute
  1751. _domute:test    valflg,-1       ; inputting now
  1752.         jnz     domutex         ; yes, just get them
  1753.         ;
  1754.         getv    al,var0         ; get mute flags
  1755.         getv    ah,var1         ; /
  1756.         not     ax              ; flip polarity
  1757.         ;
  1758.         mov     dx,ax           ; save it
  1759.         xor     ax,var4[di]     ; bits set are changes
  1760.         mov     var4[di],dx     ; save the new value
  1761.         mov     cx,ax           ; save flag bits
  1762.         not     ax              ; flip flag bits
  1763.         and     mute,ax         ; strip changed bits
  1764.         and     cx,dx           ; get new changed bits
  1765.         or      mute,cx         ; put them away
  1766.         ;
  1767. domutex:mov     dx,mute         ; get the mute word
  1768.         getv    cl,var2         ; get the shift
  1769.         ror     dx,cl           ; shift right
  1770.         not     dl              ; flip bits
  1771.         getv    al,var3         ; get mask
  1772.         and     al,dl           ; mask the mute flags
  1773.         putn    al              ; send it out
  1774.         nextv                   ; exit
  1775. ;==============================================================
  1776. ; External call via software interrupt
  1777. ; output: returned value of AL
  1778. ; inputs:
  1779. ; 0: clock
  1780. ; 1: interrupt number
  1781. ; 2: value loaded into AH
  1782. ; 3: value loaded into AL
  1783. ; 4: value loaded into BH
  1784. ; 5: value loaded into BL
  1785. ; 6: value loaded into CH
  1786. ; 7: value loaded into CL
  1787. ; 8: value loaded into DH
  1788. ; 9: value loaded into DL
  1789. ; 10x: clock tick
  1790. ;--------------------------------------------------------------
  1791.         public _xcall
  1792. _xcall: tick    var0,var10      ; tick clock
  1793.         jnc     xcallx          ; exit if no tick
  1794.         ;
  1795.         getv    al,var1         ; get the interrupt number
  1796.         test    al,-1           ; anything there
  1797.         jz      xcallx          ; no, exit
  1798.         ;
  1799.         mov     byte ptr cs:xcalli+1,al; set up the int number
  1800.         getv    ah,var2         ; load registers
  1801.         getv    al,var3         ;         /
  1802.         getv    ch,var4         ;        /
  1803.         getv    cl,var5         ;       /
  1804.         mov     bp,cx           ;      /
  1805.         getv    ch,var6         ;     /
  1806.         getv    cl,var7         ;    /
  1807.         getv    dh,var8         ;   /
  1808.         getv    dl,var9         ;  /
  1809.         mov     bx,bp           ; /
  1810.         push    si              ; save needed registers
  1811.         push    di              ;  /
  1812.         push    ds              ; /
  1813. xcalli: int     64              ; go do it
  1814.         pop     ds              ; restore registers
  1815.         pop     di              ;  /
  1816.         pop     si              ; /
  1817.         mov     xcax,ax         ; save registers
  1818.         mov     xcbx,bx         ;   /
  1819.         mov     xccx,cx         ;  /
  1820.         mov     xcdx,dx         ; /
  1821.         pushf                   ; get flags
  1822.         pop     ax              ; /
  1823.         putn    al              ; send low flags to output
  1824. xcallx: nextv                   ; exit
  1825. ;==============================================================
  1826. ; read a register after xcall
  1827. ; output: xcall register storage
  1828. ; inputs: 0: strobe, 1: register number, 2x: clock tick
  1829. ;         0 = al, 1 = ah, 2 = bl, 3 = bh, 
  1830. ;         4 = cl, 5 = bh, 6 = dl, 7 = dh
  1831. ;--------------------------------------------------------------
  1832.         public _rcall
  1833. _rcall: tick    var0,var2       ; clock tick
  1834.         jnc     rcallx          ; exit if no clock
  1835.         getv    al,var1         ; get the register number
  1836.         and     ax,7            ; 8 registers allowed
  1837.         mov     bx,offset dgroup:xcax; get table location
  1838.         add     bx,ax           ; add offset
  1839.         mov     al,[bx]         ; get the register
  1840.         putn    al              ; send it out
  1841. rcallx: nextv                   ; exit
  1842. ;==============================================================
  1843. ; read a byte from the keyboard
  1844. ; output: ascii keyboard data
  1845. ; inputs: 0: hold
  1846. ;--------------------------------------------------------------
  1847.         public _xkbd
  1848. _xkbd:
  1849.         hold    var0            ; hold?
  1850.         jnz     xkbdx           ; yes, exit
  1851.         and     byte ptr outn[di],7fh; strip old key flag
  1852.         mov     ah,6            ; dos direct console i/o
  1853.         mov     dl,0ffh         ; input request
  1854.         int     21h             ; call dos
  1855.         jz      xkbdx           ; exit if no input
  1856.         or      al,al           ; function key
  1857.         jz      xkbd0           ; yes, don't set flag
  1858.         or      al,80H          ; set new key flag
  1859. xkbd0:  putn    al              ; send it out
  1860. xkbdx:  nextv                   ; exit
  1861. ;==============================================================
  1862. ; read a byte from MIDI to s-sequencer
  1863. ; output: index into s-sequencer
  1864. ; inputs: 0: reset strobe, 1: enable, 2x: tick
  1865. ;--------------------------------------------------------------
  1866.         public _xmidii
  1867. _xmidii:
  1868.         tick    var0,var2       ; strobe tick?
  1869.         jnc     xmidii0         ; no, branch
  1870.         mov     cs:midatix,0    ; yes, clear index
  1871.         ;
  1872. xmidii0:getv    al,var1         ; get write enable flag
  1873.         mov     cs:misend,al    ; set/clear the flag
  1874.         ;
  1875.         mov     al,cs:midatix   ; get index
  1876.         putn    al              ; send it out
  1877.         nextv                   ; exit
  1878. ;==============================================================
  1879. ; show output buffer status
  1880. ; inputs: none
  1881. ; output: flag bits 0,1 set if output buffer not empty
  1882. ;--------------------------------------------------------------
  1883.         public  _tstmob
  1884. _tstmob:call    tstmob          ; check it
  1885.         putn    al              ; send it out
  1886.         nextl                   ; show it
  1887. ;==============================================================
  1888. ; show mpu input flags, set mpu input mask
  1889. ;   0 = no input, 1=mpu#1, 2=mpu#2
  1890. ; inputs: 0: reset input flag
  1891. ;         1: mpu input mask
  1892. ;         2x init flag
  1893. ; output: mpu input flags
  1894. ;--------------------------------------------------------------
  1895.         public  _mpuins
  1896. _mpuins:cmp     byte ptr var2[di],0abh  ; initialized?
  1897.         jnz     mpuins0                 ; no, branch
  1898.         ;
  1899.         getv    al,var1                 ; get mask byte
  1900.         mov     cs:_mpuinm,al           ; set mask
  1901.         ;
  1902.         mov     al,cs:_mpuinf           ; get mpu input flag
  1903.         putn    al                      ; send it out
  1904.         ;
  1905.         testv   var0,-1                 ; want to clear mpu flag?
  1906.         jnz     mpuins1                 ; no, branch
  1907.         mov     cs:_mpuinf,0            ; clear mpu flag
  1908.         ;
  1909. mpuins1:nextl                           ; show it
  1910.         ;
  1911. mpuins0:mov     byte ptr var2[di],0abh  ; no, set init values
  1912.         initv   var1,3                  ; default is all ok
  1913.         nextx                           ; exit
  1914. ;;==============================================================
  1915. ; output a byte to output port
  1916. ; output: none
  1917. ; inputs:
  1918. ; 0: clock
  1919. ; 1: value to be output
  1920. ; 2: output port address hi
  1921. ; 3: output port address lo
  1922. ; 4x: clock tick
  1923. ;--------------------------------------------------------------
  1924.         public _outpb
  1925. _outpb: tick    var0,var4       ; clock tick
  1926.         jnc     outpbx          ; exit if no clock
  1927.         getv    dh,var2         ; get the address
  1928.         getv    dl,var3         ; /
  1929.         getv    al,var1         ; get the value
  1930.         out     dx,al           ; send it out
  1931. outpbx: nextx                   ; exit
  1932. ;==============================================================
  1933. ; input a byte from input port
  1934. ; output: value from port
  1935. ; inputs:
  1936. ; 0: clock
  1937. ; 1: input port address hi
  1938. ; 2: input port address lo
  1939. ; 3x: clock tick
  1940. ;--------------------------------------------------------------
  1941.         public _inptb
  1942. _inptb: tick    var0,var3       ; clock tick
  1943.         jnc     inptbx          ; exit if no clock
  1944.         getv    dh,var1         ; get the address
  1945.         getv    dl,var2         ; /
  1946.         in      al,dx           ; get the value from port
  1947.         putn    al              ; send it
  1948. inptbx: nextv                   ; exit & show
  1949. ;==============================================================
  1950. ; input a byte from memory
  1951. ; output: value from memory
  1952. ; inputs:
  1953. ; 0: clock
  1954. ; 1: seg addr hi
  1955. ; 2: input port address hi
  1956. ; 3: input port address lo
  1957. ; 4x: clock tick
  1958. ;--------------------------------------------------------------
  1959.         public _peek
  1960. _peek:  tick    var0,var4       ; clock tick
  1961.         jnc     peekx           ; exit if no clock
  1962.         getv    dh,var1         ; get seg hi
  1963.         getv    ah,var2         ; get address hi
  1964.         getv    bl,var3         ; get address lo
  1965.         mov     bh,ah           ; bx = address
  1966.         mov     dl,0            ; dx = seg
  1967.         mov     es,dx           ; es = seg
  1968.         mov     al,es:[bx]      ; get the byte
  1969.         putn    al              ; send it
  1970. peekx:  nextv                   ; exit & show
  1971. ;==============================================================
  1972. ; output a byte to memory
  1973. ; output: none
  1974. ; inputs:
  1975. ; 0: clock
  1976. ; 1: value to be output
  1977. ; 2: seg addr hi
  1978. ; 3: input port address hi
  1979. ; 4: input port address lo
  1980. ; 5x: clock tick
  1981. ;--------------------------------------------------------------
  1982.         public _poke
  1983. _poke:  tick    var0,var5       ; clock tick
  1984.         jnc     pokex           ; exit if no clock
  1985.         getv    al,var1         ; get the value
  1986.         getv    dh,var2         ; get seg hi
  1987.         getv    ah,var3         ; get address hi
  1988.         getv    bl,var4         ; get address lo
  1989.         mov     bh,ah           ; bx = address
  1990.         mov     dl,0            ; dx = seg
  1991.         mov     es,dx           ; es = seg
  1992.         mov     es:[bx],al      ; put the byte
  1993.         putn    al              ; send it
  1994. pokex:  nextx                   ; exit
  1995. ;==============================================================
  1996. ; System Exclusive Receive
  1997. ; inputs:
  1998. ;   0:    Address Low of sequencer "S" where data will go
  1999. ;   1:    Address High of sequencer "S"
  2000. ;   2:    Strobe to start receive
  2001. ;   3:    Shift output value
  2002. ;   4xz:  Index into seq "s"
  2003. ;   5x:   strobe tick
  2004. ; output: Next available seq addr, shifted right by input 3
  2005. ;--------------------------------------------------------------
  2006.         public _sxget
  2007. _sxget: tick    var2,var5               ; wanna do it?
  2008.         jc      sxget0                  ; yes, branch
  2009.         jmp     sxgetx                  ; no, exit to readout
  2010.         ;
  2011. sxget0: mov     es,4[di]                ; get seg addr
  2012.         mov     bx,6[di]                ; get module screen address
  2013.         mov     al,'X'                  ; set output byte
  2014.         mov     es:320[bx],al           ; put to the screen
  2015.         mov     es:322[bx],al           ; /
  2016.         mov     ax,80H                  ; to set hi bit
  2017.         mov     outn[di],ax             ; trash output
  2018.         or      es:321[bx],al           ; put to the screen
  2019.         or      es:323[bx],al           ; /
  2020.         ;
  2021. sxget6: call    allclr                  ; clear midi channel
  2022.         ; 
  2023.         mov     word ptr var4[di],-2    ; setup error flag
  2024.         mov     cs:miflag,0             ; clear input data flag
  2025.         ;
  2026.         mov     ax,seg buffs            ; setup seg register
  2027.         mov     es,ax                   ; es = seg addr
  2028.         getv    dl,var0                 ; get address lo
  2029.         getv    dh,var1                 ; get address hi
  2030.         mov     bx,dx                   ; set up as index
  2031.         ;
  2032.         mov     bp,cs:ticks             ; get timer
  2033.         add     bp,11640                ; timeout in 20 sec.
  2034.         ;
  2035. sxget1: test    cs:miflag,-1            ; anything there?
  2036.         jnz     sxget2                  ; yes, branch
  2037.         cmp     bp,cs:ticks             ; timeout?
  2038.         jnz     sxget1                  ; no, keep looking
  2039.         jmp     sxgetx                  ; yes, exit
  2040.         ;
  2041. sxget2: mov     cs:miflag,0             ; clear input flag
  2042.         cmp     cs:midata,0f0h          ; system exclusive?
  2043.         jnz     sxget1                  ; no, keep looking
  2044.         mov     byte ptr es:[bx],0f0h   ; yes, send the data
  2045.         inc     bx                      ; bump index
  2046.         jz      sxgetx                  ; exit if index overflow
  2047.         ;
  2048. sxget3: test    cs:miflag,-1            ; anything there?
  2049.         jnz     sxget4                  ; yes, branch
  2050.         cmp     bp,cs:ticks             ; timeout?
  2051.         jnz     sxget3                  ; no, keep looking
  2052.         ;
  2053. sxget4: mov     cs:miflag,0             ; clear input flag
  2054.         mov     al,cs:midata            ; get the data
  2055.         mov     es:[bx],al              ; put it in the seq memory
  2056.         cmp     al,0f7h                 ; EOX?
  2057.         jz      sxget5                  ; yes, branch
  2058.         inc     bx                      ; bump index
  2059.         jz      sxgetx                  ; exit if index overflow
  2060.         jmp     short sxget3            ; else back to the loop
  2061.         ;
  2062. sxget5: mov     var4[di],bx             ; set the new index
  2063.         mov     _header+7,1             ; set buffer used flag
  2064.         ;
  2065. sxgetx: mov     ax,var4[di]             ; get the index
  2066.         inc     ax                      ; bump one
  2067.         getv    cl,var3                 ; get shift byte
  2068.         shr     ax,cl                   ; bump right
  2069.         putn    al                      ; send it out
  2070.         mov     al,7fH                  ; to set lo bit
  2071.         mov     es,4[di]                ; get seg addr
  2072.         mov     bx,6[di]                ; get module screen address
  2073.         and     es:321[bx],al           ; put to the screen
  2074.         and     es:323[bx],al           ; /
  2075.         nextv                           ; exit
  2076. ;==============================================================
  2077. ; System Exclusive Send
  2078. ; inputs:
  2079. ;   0:    Address Low of sequencer "S" where data is found
  2080. ;   1:    Address High of sequencer "S"
  2081. ;   2:    Strobe to start send
  2082. ;   3:    Shift output value
  2083. ;   4xz:  Index into seq "s"
  2084. ;   5x:   strobe tick
  2085. ; output: Next available seq addr, shifted right by input 3
  2086. ;--------------------------------------------------------------
  2087.         public _sxput
  2088. _sxput: tick    var2,var5               ; wanna do it?
  2089.         jc      sxput0                  ; yes, branch
  2090.         jmp     sxputx                  ; no, exit to readout
  2091.         ;
  2092. sxput0: mov     word ptr var4[di],-2    ; setup error flag
  2093.         mov     midip,0                 ; set midi port 0
  2094.         ;
  2095.         mov     es,4[di]                ; get seg addr
  2096.         mov     bx,6[di]                ; get module screen address
  2097.         mov     al,'X'                  ; set output byte
  2098.         mov     es:320[bx],al           ; put to the screen
  2099.         mov     es:322[bx],al           ; /
  2100.         mov     ax,80H                  ; to set hi bit
  2101.         mov     outn[di],ax             ; trash output
  2102.         or      es:321[bx],al           ; put to the screen
  2103.         or      es:323[bx],al           ; /
  2104.         ;
  2105.         mov     ax,seg buffs            ; setup seg register
  2106.         mov     es,ax                   ; es = seg addr
  2107.         getv    dl,var0                 ; get address lo
  2108.         getv    dh,var1                 ; get address hi
  2109.         mov     bp,dx                   ; set up as index
  2110.         ;
  2111. sxput1: call    allclr                  ; clear midi channels
  2112.         ;
  2113. sxput2: mov     al,es:[bp]              ; get the data byte
  2114.         mov     ah,al                   ; save in ah
  2115.         call    allmidi                 ; send it to buffer
  2116.         sendmb                          ; send it to MIDI
  2117.         ;
  2118.         cmp     ah,0f7h                 ; EOX?
  2119.         jz      sxput3                  ; yes, branch
  2120.         inc     bp                      ; bump index
  2121.         jz      sxputx                  ; exit if index overflow
  2122.         jmp     short sxput2            ; else back to the loop
  2123.         ;
  2124. sxput3: mov     var4[di],bp             ; set the new index
  2125.         ;
  2126. sxputx: mov     ax,var4[di]             ; get the index
  2127.         inc     ax                      ; bump one
  2128.         getv    cl,var3                 ; get shift byte
  2129.         shr     ax,cl                   ; bump right
  2130.         putn    al                      ; send it out
  2131.         mov     al,7fH                  ; to set lo bit
  2132.         mov     es,4[di]                ; get seg addr
  2133.         mov     bx,6[di]                ; get module screen address
  2134.         and     es:321[bx],al           ; put to the screen
  2135.         and     es:323[bx],al           ; /
  2136.         nextv                           ; exit
  2137. ;==============================================================
  2138. ; MIDI Program change
  2139. ; inputs: 
  2140. ;       0:  channel
  2141. ;       1:  delay  
  2142. ;       2:  strobe
  2143. ;       3:  input
  2144. ;       4x: strobe tick
  2145. ; output: none
  2146. ;--------------------------------------------------------------
  2147.         public _patcho        
  2148. _patcho:
  2149.         test    lodflg,-1               ; load happen?
  2150.         jnz     patcho1                 ; yes, force change
  2151.         test    clrchf,3                ; clear chan flag?
  2152.         jz      patcho2                 ; yes, force change
  2153.         or      clrchf,2                ; setup to clear
  2154.         jmp     patcho1                 ; go do it
  2155.         ;
  2156. patcho2:tick    var2,var4               ; clock tick
  2157.         jnc     patchox                 ; exit if no strobe
  2158.         ;
  2159. patcho1:call    allclr                  ; clear all midi channels
  2160.         getv    al,var0                 ; get channel
  2161.         mchan   al                      ; /
  2162.         or      al,0c0H                 ; MIDI Program Change
  2163.         call    tomidi                  ; send it to midi
  2164.         ;
  2165.         getv    al,var3                 ; get value input
  2166.         mov     outn[di],al             ; send to output
  2167.         and     al,127                  ; strip msb
  2168.         call    tomidi                  ; send to midi
  2169.         ;
  2170.         getv    al,var1                 ; get delay value
  2171.         or      al,al                   ; split if 0
  2172.         jz      patchox                 ; /
  2173.         mov     ah,0                    ; make it a word
  2174.         add     ax,cs:ticks             ; add current ticks
  2175. patcho0:cmp     al,byte ptr cs:ticks    ; reached it yet?
  2176.         jnz     patcho0                 ; no, loop
  2177. patchox:nextv
  2178. ;==============================================================
  2179. ; Programmer output values
  2180. ; inputs: 0x: channel
  2181. ; output: sequencer send to the controller
  2182. ;--------------------------------------------------------------
  2183.         public _pcouta
  2184. _pcouta:cmp     byte ptr var0+1[di],0abh; initialized?
  2185.         jz      pcouta0                 ; yes, branch
  2186.         ;
  2187. pcouti: mov     al,modnum               ; get module number
  2188.         mov     var0[di],al             ; save it
  2189.  
  2190.         gettag                          ; es:bx = screen addr of tag
  2191.         tohex                           ; convert to hex
  2192.         mov     es:-2[bx],al            ; show the default number
  2193.         mov     byte ptr var0+1[di],0abh; set init flag
  2194.         nextx
  2195.         ;
  2196. pcouta0:test    usrflg,1                ; user input
  2197.         jnz     pcoutax                 ; yes, no go
  2198.         mov     bl,var0[di]             ; get channel
  2199.         mov     bh,0                    ; bx = channel
  2200.         add     bx,offset dgroup:pcva   ; add table to offset
  2201.         mov     al,[bx]                 ; get the value
  2202.         putn    al                      ; send it out
  2203. pcoutax:nextv                           ; exit with display
  2204. ;--------------------------------------------------------------
  2205.         public _pcoutb
  2206. _pcoutb:cmp     byte ptr var0+1[di],0abh; initialized?
  2207.         jz      pcoutb0                 ; yes, branch
  2208.         jmp     pcouti                  ; no, initialize
  2209.         ;
  2210. pcoutb0:test    usrflg,1                ; user input
  2211.         jnz     pcoutbx                 ; yes, no go
  2212.         mov     bl,var0[di]             ; get channel
  2213.         mov     bh,0                    ; bx = channel
  2214.         add     bx,offset dgroup:pcvb   ; add table to offset
  2215.         mov     al,[bx]                 ; get the value
  2216.         putn    al                      ; send it out
  2217. pcoutbx:nextv                           ; exit with display
  2218. ;--------------------------------------------------------------
  2219.         public _pcoutc
  2220. _pcoutc:cmp     byte ptr var0+1[di],0abh; initialized?
  2221.         jz      pcoutc0                 ; yes, branch
  2222.         jmp     pcouti                  ; no, initialize
  2223.         ;
  2224. pcoutc0:test    usrflg,1                ; user input
  2225.         jnz     pcoutcx                 ; yes, no go
  2226.         mov     bl,var0[di]             ; get channel
  2227.         mov     bh,0                    ; bx = channel
  2228.         add     bx,offset dgroup:pcvc   ; add table to offset
  2229.         mov     al,[bx]                 ; get the value
  2230.         putn    al                      ; send it out
  2231. pcoutcx:nextv                           ; exit with display
  2232. ;--------------------------------------------------------------
  2233.         public _pcoutd
  2234. _pcoutd:cmp     byte ptr var0+1[di],0abh; initialized?
  2235.         jz      pcoutd0                 ; yes, branch
  2236.         jmp     pcouti                  ; no, initialize
  2237.         ;
  2238. pcoutd0:test    usrflg,1                ; user input
  2239.         jnz     pcoutdx                 ; yes, no go
  2240.         mov     bl,var0[di]             ; get channel
  2241.         mov     bh,0                    ; bx = channel
  2242.         add     bx,offset dgroup:pcvd   ; add table to offset
  2243.         mov     al,[bx]                 ; get the value
  2244.         putn    al                      ; send it out
  2245. pcoutdx:nextv                           ; exit with display
  2246. ;--------------------------------------------------------------
  2247.         public _pcoute
  2248. _pcoute:cmp     byte ptr var0+1[di],0abh; initialized?
  2249.         jz      pcoute0                 ; yes, branch
  2250.         jmp     pcouti                  ; no, initialize
  2251.         ;
  2252. pcoute0:test    usrflg,1                ; user input
  2253.         jnz     pcoutex                 ; yes, no go
  2254.         mov     bl,var0[di]             ; get channel
  2255.         mov     bh,0                    ; bx = channel
  2256.         add     bx,offset dgroup:pcve   ; add table to offset
  2257.         mov     al,[bx]                 ; get the value
  2258.         putn    al                      ; send it out
  2259. pcoutex:nextv                           ; exit with display
  2260. ;--------------------------------------------------------------
  2261.         public _pcoutf
  2262. _pcoutf:cmp     byte ptr var0+1[di],0abh; initialized?
  2263.         jz      pcoutf0                 ; yes, branch
  2264.         jmp     pcouti                  ; no, initialize
  2265.         ;
  2266. pcoutf0:test    usrflg,1                ; user input
  2267.         jnz     pcoutfx                 ; yes, no go
  2268.         mov     bl,var0[di]             ; get channel
  2269.         mov     bh,0                    ; bx = channel
  2270.         add     bx,offset dgroup:pcvf   ; add table to offset
  2271.         mov     al,[bx]                 ; get the value
  2272.         putn    al                      ; send it out
  2273. pcoutfx:nextv                           ; exit with display
  2274. ;--------------------------------------------------------------
  2275.         public _pcoutg
  2276. _pcoutg:cmp     byte ptr var0+1[di],0abh; initialized?
  2277.         jz      pcoutg0                 ; yes, branch
  2278.         jmp     pcouti                  ; no, initialize
  2279.         ;
  2280. pcoutg0:test    usrflg,1                ; user input
  2281.         jnz     pcoutgx                 ; yes, no go
  2282.         mov     bl,var0[di]             ; get channel
  2283.         mov     bh,0                    ; bx = channel
  2284.         add     bx,offset dgroup:pcvg   ; add table to offset
  2285.         mov     al,[bx]                 ; get the value
  2286.         putn    al                      ; send it out
  2287. pcoutgx:nextv                           ; exit with display
  2288. ;--------------------------------------------------------------
  2289.         public _pcouth
  2290. _pcouth:cmp     byte ptr var0+1[di],0abh; initialized?
  2291.         jz      pcouth0                 ; yes, branch
  2292.         jmp     pcouti                  ; no, initialize
  2293.         ;
  2294. pcouth0:test    usrflg,1                ; user input
  2295.         jnz     pcouthx                 ; yes, no go
  2296.         mov     bl,var0[di]             ; get channel
  2297.         mov     bh,0                    ; bx = channel
  2298.         add     bx,offset dgroup:pcvh   ; add table to offset
  2299.         mov     al,[bx]                 ; get the value
  2300.         putn    al                      ; send it out
  2301. pcouthx:nextv                           ; exit with display
  2302. ;--------------------------------------------------------------
  2303.         public _pcoutx
  2304. _pcoutx:cmp     byte ptr var0+1[di],0abh; initialized?
  2305.         jz      pcoutx0                 ; yes, branch
  2306.         jmp     pcouti                  ; no, initialize
  2307.         ;
  2308. pcoutx0:test    usrflg,1                ; user input
  2309.         jnz     pcoutxx                 ; yes, no go
  2310.         mov     bl,var0[di]             ; get channel
  2311.         mov     bh,0                    ; bx = channel
  2312.         add     bx,offset dgroup:pcvx   ; add table to offset
  2313.         mov     al,[bx]                 ; get the value
  2314.         putn    al                      ; send it out
  2315. pcoutxx:nextv                           ; exit with display
  2316. ;--------------------------------------------------------------
  2317.         public _pcouty
  2318. _pcouty:cmp     byte ptr var0+1[di],0abh; initialized?
  2319.         jz      pcouty0                 ; yes, branch
  2320.         jmp     pcouti                  ; no, initialize
  2321.         ;
  2322. pcouty0:test    usrflg,1                ; user input
  2323.         jnz     pcoutyx                 ; yes, no go
  2324.         mov     bl,var0[di]             ; get channel
  2325.         mov     bh,0                    ; bx = channel
  2326.         add     bx,offset dgroup:pcvy   ; add table to offset
  2327.         mov     al,[bx]                 ; get the value
  2328.         putn    al                      ; send it out
  2329. pcoutyx:nextv                           ; exit with display
  2330. ;--------------------------------------------------------------
  2331.         public _pcoutz
  2332. _pcoutz:cmp     byte ptr var0+1[di],0abh; initialized?
  2333.         jz      pcoutz0                 ; yes, branch
  2334.         jmp     pcouti                  ; no, initialize
  2335.         ;
  2336. pcoutz0:test    usrflg,1                ; user input
  2337.         jnz     pcoutzx                 ; yes, no go
  2338.         mov     bl,var0[di]             ; get channel
  2339.         mov     bh,0                    ; bx = channel
  2340.         add     bx,offset dgroup:pcvz   ; add table to offset
  2341.         mov     al,[bx]                 ; get the value
  2342.         putn    al                      ; send it out
  2343. pcoutzx:nextv                           ; exit with display
  2344. ;--------------------------------------------------------------
  2345. ; magenta input
  2346. ;
  2347.         public  upcout
  2348. upcout: pop     ax              ; stack bullshit
  2349.         mov     cmdflg,10       ; set up special routine
  2350.         mov     special,offset upcoutx
  2351.         mov     di,varsav       ; point to variable list
  2352.         mov     al,outn[di]     ; get the output value
  2353.         mov     var0[di],al     ; save
  2354.         jmp     workx           ; on to the next stage
  2355.  
  2356. upcoutx:mov     di,varsav       ; point to variable list
  2357.         mov     al,outn[di]     ; get the new channel
  2358.         xchg    var0[di],al     ; set it, get orig patch
  2359.         mov     outn[di],al     ; restore
  2360.         jmp     _cancel         ; exit
  2361. ;==============================================================
  2362. ; add switch
  2363. ; inputs: 0:   switch bits
  2364. ;         1-8: switch inputs  
  2365. ; output: sequencer send to the controller
  2366. ;--------------------------------------------------------------
  2367.         public _addswa
  2368. _addswa:getv    dl,var0                 ; get the bits byte
  2369.         gettag                          ; es:bx = screen addr of tag
  2370.         dec     bx                      ; drop back 1 for led
  2371.         add     bx,640                  ; bx = screen addr of 1st stage led
  2372.         mov     bp,bx                   ; bp = leds
  2373.         add     di,var1                 ; point to first stage
  2374.         ;
  2375.         mov     ah,1                    ; set bit flag
  2376.         mov     al,0                    ; clear the add register
  2377.         mov     cx,8                    ; 8 to do
  2378. addswa1:
  2379.         test    dl,ah                   ; is the bit hi?
  2380.         jz      addswa3                 ; no, turn it off
  2381.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2382.         mov     bx,[di]                 ; get the value addr
  2383.         add     al,[bx]                 ; add in the value
  2384.         jmp     short addswa4           ; branch
  2385. addswa3:
  2386.         mov     byte ptr es:[bp],yellow ; turn the led off
  2387. addswa4:
  2388.         add     di,2                    ; point to next val
  2389.         shl     ah,1                    ; bump bit pointer
  2390.         add     bp,160                  ; point to next led
  2391.         loop    addswa1                 ; do it again
  2392.         ;
  2393.         mov     di,2[si]                ; set di pointing to variable list
  2394.         putn    al                      ; send it out
  2395. addswax:nextv                           ; exit with display
  2396. ;==============================================================
  2397. ; Programmer add switch output values
  2398. ; inputs: 0-3: switch inputs  
  2399. ;         4: control byte
  2400. ; output: sequencer send to the controller
  2401. ;--------------------------------------------------------------
  2402.         public _psouta
  2403. _psouta:getv    dl,var4                 ; get the value
  2404.         mov     cl,4                    ; get shift
  2405.         shr     dl,cl                   ; shift down
  2406.         and     dl,15                   ; mask
  2407.         ;
  2408.         gettag                          ; es:bx = screen addr of tag
  2409.         dec     bx                      ; drop back 1 for led
  2410.         add     bx,480                  ; bx = screen addr of 1st stage led
  2411.         mov     bp,bx                   ; bp = leds
  2412.         add     di,var0                 ; point to first stage
  2413.         ;
  2414.         mov     ah,1                    ; set bit flag
  2415.         mov     al,0                    ; clear the add register
  2416.         mov     cx,4                    ; 4 to do
  2417. psouta1:
  2418.         test    dl,ah                   ; is the bit hi?
  2419.         jz      psouta3                 ; no, turn it off
  2420.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2421.         mov     bx,[di]                 ; get the value addr
  2422.         add     al,[bx]                 ; add in the value
  2423.         jmp     short psouta4           ; branch
  2424. psouta3:
  2425.         mov     byte ptr es:[bp],yellow ; turn the led off
  2426. psouta4:
  2427.         add     di,2                    ; point to next val
  2428.         shl     ah,1                    ; bump bit pointer
  2429.         add     bp,160                  ; point to next led
  2430.         loop    psouta1                 ; do it again
  2431.         ;
  2432.         mov     di,2[si]                ; set di pointing to variable list
  2433.         putn    al                      ; send it out
  2434. psoutax:nextv                           ; exit with display
  2435. ;--------------------------------------------------------------
  2436.         public _psoutc
  2437. _psoutc:getv    dl,var4                 ; get the value
  2438.         mov     cl,4                    ; get shift
  2439.         shr     dl,cl                   ; shift down
  2440.         and     dl,15                   ; mask
  2441.         ;
  2442.         gettag                          ; es:bx = screen addr of tag
  2443.         dec     bx                      ; drop back 1 for led
  2444.         add     bx,480                  ; bx = screen addr of 1st stage led
  2445.         mov     bp,bx                   ; bp = leds
  2446.         add     di,var0                 ; point to first stage
  2447.         ;
  2448.         mov     ah,1                    ; set bit flag
  2449.         mov     al,0                    ; clear the add register
  2450.         mov     cx,4                    ; 4 to do
  2451. psoutc1:
  2452.         test    dl,ah                   ; is the bit hi?
  2453.         jz      psoutc3                 ; no, turn it off
  2454.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2455.         mov     bx,[di]                 ; get the value addr
  2456.         add     al,[bx]                 ; add in the value
  2457.         jmp     short psoutc4           ; branch
  2458. psoutc3:
  2459.         mov     byte ptr es:[bp],yellow ; turn the led off
  2460. psoutc4:
  2461.         add     di,2                    ; point to next val
  2462.         shl     ah,1                    ; bump bit pointer
  2463.         add     bp,160                  ; point to next led
  2464.         loop    psoutc1                 ; do it again
  2465.         ;
  2466.         mov     di,2[si]                ; set di pointing to variable list
  2467.         putn    al                      ; send it out
  2468. psoutcx:nextv                           ; exit with display
  2469. ;--------------------------------------------------------------
  2470.         public _psoutb
  2471. _psoutb:getv    dl,var4                 ; get the value
  2472.         and     dl,15                   ; mask
  2473.         ;
  2474.         gettag                          ; es:bx = screen addr of tag
  2475.         dec     bx                      ; drop back 1 for led
  2476.         add     bx,480                  ; bx = screen addr of 1st stage led
  2477.         mov     bp,bx                   ; bp = leds
  2478.         add     di,var0                 ; point to first stage
  2479.         ;
  2480.         mov     ah,1                    ; set bit flag
  2481.         mov     al,0                    ; clear the add register
  2482.         mov     cx,4                    ; 4 to do
  2483. psoutb1:
  2484.         test    dl,ah                   ; is the bit hi?
  2485.         jz      psoutb3                 ; no, turn it off
  2486.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2487.         mov     bx,[di]                 ; get the value addr
  2488.         add     al,[bx]                 ; add in the value
  2489.         jmp     short psoutb4           ; branch
  2490. psoutb3:
  2491.         mov     byte ptr es:[bp],yellow ; turn the led off
  2492. psoutb4:
  2493.         add     di,2                    ; point to next val
  2494.         shl     ah,1                    ; bump bit pointer
  2495.         add     bp,160                  ; point to next led
  2496.         loop    psoutb1                 ; do it again
  2497.         ;
  2498.         mov     di,2[si]                ; set di pointing to variable list
  2499.         putn    al                      ; send it out
  2500. psoutbx:nextv                           ; exit with display
  2501. ;--------------------------------------------------------------
  2502.         public _psoutd
  2503. _psoutd:getv    dl,var4                 ; get the value
  2504.         and     dl,15                   ; mask
  2505.         ;
  2506.         gettag                          ; es:bx = screen addr of tag
  2507.         dec     bx                      ; drop back 1 for led
  2508.         add     bx,480                  ; bx = screen addr of 1st stage led
  2509.         mov     bp,bx                   ; bp = leds
  2510.         add     di,var0                 ; point to first stage
  2511.         ;
  2512.         mov     ah,1                    ; set bit flag
  2513.         mov     al,0                    ; clear the add register
  2514.         mov     cx,4                    ; 4 to do
  2515. psoutd1:
  2516.         test    dl,ah                   ; is the bit hi?
  2517.         jz      psoutd3                 ; no, turn it off
  2518.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2519.         mov     bx,[di]                 ; get the value addr
  2520.         add     al,[bx]                 ; add in the value
  2521.         jmp     short psoutd4           ; branch
  2522. psoutd3:
  2523.         mov     byte ptr es:[bp],yellow ; turn the led off
  2524. psoutd4:
  2525.         add     di,2                    ; point to next val
  2526.         shl     ah,1                    ; bump bit pointer
  2527.         add     bp,160                  ; point to next led
  2528.         loop    psoutd1                 ; do it again
  2529.         ;
  2530.         mov     di,2[si]                ; set di pointing to variable list
  2531.         putn    al                      ; send it out
  2532. psoutdx:nextv                           ; exit with display
  2533. ;==============================================================
  2534. ; Programmer add switch output values
  2535. ; inputs: 0-3: switch inputs  
  2536. ;         4: control byte 5: shift
  2537. ; output: sequencer send to the controller
  2538. ;--------------------------------------------------------------
  2539.         public _psoute
  2540. _psoute:getv    dl,var4                 ; get the value
  2541.         getv    cl,var5                 ; get shift
  2542.         shr     dl,cl                   ; shift down
  2543.         and     dl,15                   ; mask
  2544.         ;
  2545.         gettag                          ; es:bx = screen addr of tag
  2546.         dec     bx                      ; drop back 1 for led
  2547.         add     bx,480                  ; bx = screen addr of 1st stage led
  2548.         mov     bp,bx                   ; bp = leds
  2549.         add     di,var0                 ; point to first stage
  2550.         ;
  2551.         mov     ah,1                    ; set bit flag
  2552.         mov     al,0                    ; clear the add register
  2553.         mov     cx,4                    ; 4 to do
  2554. psoute1:
  2555.         test    dl,ah                   ; is the bit hi?
  2556.         jz      psoute3                 ; no, turn it off
  2557.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2558.         mov     bx,[di]                 ; get the value addr
  2559.         add     al,[bx]                 ; add in the value
  2560.         jmp     short psoute4           ; branch
  2561. psoute3:
  2562.         mov     byte ptr es:[bp],yellow ; turn the led off
  2563. psoute4:
  2564.         add     di,2                    ; point to next val
  2565.         shl     ah,1                    ; bump bit pointer
  2566.         add     bp,160                  ; point to next led
  2567.         loop    psoute1                 ; do it again
  2568.         ;
  2569.         mov     di,2[si]                ; set di pointing to variable list
  2570.         putn    al                      ; send it out
  2571. psoutex:nextv                           ; exit with display
  2572. ;--------------------------------------------------------------
  2573.         public _psoutf
  2574. _psoutf:getv    dl,var4                 ; get the value
  2575.         getv    cl,var5                 ; get shift
  2576.         shr     dl,cl                   ; shift down
  2577.         and     dl,15                   ; mask
  2578.         ;
  2579.         gettag                          ; es:bx = screen addr of tag
  2580.         dec     bx                      ; drop back 1 for led
  2581.         add     bx,480                  ; bx = screen addr of 1st stage led
  2582.         mov     bp,bx                   ; bp = leds
  2583.         add     di,var0                 ; point to first stage
  2584.         ;
  2585.         mov     ah,1                    ; set bit flag
  2586.         mov     al,0                    ; clear the add register
  2587.         mov     cx,4                    ; 4 to do
  2588. psoutf1:
  2589.         test    dl,ah                   ; is the bit hi?
  2590.         jz      psoutf3                 ; no, turn it off
  2591.         mov     byte ptr es:[bp],red+hi ; else turn the led on
  2592.         mov     bx,[di]                 ; get the value addr
  2593.         add     al,[bx]                 ; add in the value
  2594.         jmp     short psoutf4           ; branch
  2595. psoutf3:
  2596.         mov     byte ptr es:[bp],yellow ; turn the led off
  2597. psoutf4:
  2598.         add     di,2                    ; point to next val
  2599.         shl     ah,1                    ; bump bit pointer
  2600.         add     bp,160                  ; point to next led
  2601.         loop    psoutf1                 ; do it again
  2602.         ;
  2603.         mov     di,2[si]                ; set di pointing to variable list
  2604.         putn    al                      ; send it out
  2605. psoutfx:nextv                           ; exit with display
  2606. ;==============================================================
  2607. ; MIDI sys excl send (8 bytes max)
  2608. ; inputs: 0: trigger, 1-8 input values to send, 9x: clock tick
  2609. ; output: none
  2610. ;--------------------------------------------------------------
  2611.         public _sysxo
  2612. _sysxo:
  2613.         tick    var0,var9       ;
  2614.         jnc     sysxox          ; exit if no tick
  2615.         mov     al,0F0H         ; send sys ex opcode
  2616.         call    allmidi         ; send to midi
  2617.         mov     cx,8            ; 8 data bytes
  2618. sysxo1: getv    al,var1         ; get byte
  2619.         test    al,80H          ; don't send if ms bit is hi
  2620.         jnz     sysxo2          ; /
  2621.         call    allmidi         ; else dump to midi
  2622. sysxo2: add     di,2            ; bump pointer
  2623.         loop    sysxo1          ; do them all
  2624.         mov     al,0F7H         ; send eox
  2625.         call    allmidi         ; /
  2626. sysxox: nextx                   ; exit
  2627. ;==============================================================
  2628. ; MIDI Control change
  2629. ; inputs: 0: clock, 1: channel, 2: Control number, 3: Control value
  2630. ;         4x: clock tick
  2631. ; output: none
  2632. ;--------------------------------------------------------------
  2633.         public _ctrlo
  2634. _ctrlo: 
  2635.         tick    var0,var4       ; clock tick
  2636.         jnc     ctrlox          ; exit if no tick
  2637.         getv    al,var1         ; get channel
  2638.         mchan   al              ; strip & set
  2639.         or      al,0B0H         ; MIDI Control Change
  2640.         call    tomidi          ; send it to midi
  2641.         getv    al,var2         ; get control number
  2642.         and     al,127          ; /
  2643.         call    tomidi          ; send data to midi
  2644.         getv    al,var3         ; get control value
  2645.         and     al,127          ; /
  2646.         call    tomidi          ; send data to midi
  2647. ctrlox: nextx
  2648. ;==============================================================
  2649. ; MIDI Control mapping
  2650. ; first group of control modules
  2651. ;--------------------------------------------------------------
  2652.  
  2653.         public _mapo   
  2654. _mapo:  test    usrflg,1                ; inputting now
  2655.         jnz     mapox                   ; yes, exit
  2656.         ;
  2657.         mov     bp,si                   ; save si
  2658.         mov     si,6[di]                ; set up for show
  2659.         mov     es,4[di]                ; /
  2660.         mov     bx,offset dgroup:ctrlmap; point to control map
  2661.         add     si,320                  ; point to 1st value screen location
  2662.         add     di,var0                 ; point to 1st value in module
  2663.         mov     cx,8                    ; # of values
  2664.         ;
  2665. mapo1:  mov     al,[bx]                 ; look at value
  2666.         cmp     al,[di]                 ; same as in module?
  2667.         jz      mapo1a                  ; yes, branch
  2668.         mov     [di],al                 ; no, make same
  2669.         tohex   al                      ; display
  2670.         mov     es:[si],ah              ;  /
  2671.         mov     es:2[si],al             ; /
  2672. mapo1a: inc     bx                      ; next map number
  2673.         add     di,2                    ; next value location
  2674.         add     si,160                  ; next screen location
  2675.         loop    mapo1                   ; do another
  2676.         ;
  2677.         mov     si,bp                   ; restore si
  2678. mapox:  nextx                           ; exit
  2679. ;--------------------------------------------------------------
  2680.         public umapo
  2681. umapo:  pop     ax              ; stack bullshit
  2682.         mov     cmdflg,10       ; set up special routine
  2683.         mov     special,offset umapox
  2684.         jmp     workx           ; on to the next stage
  2685.  
  2686. umapox:
  2687.         mov     bx,holdv        ; get offset to the value
  2688.         mov     di,varsav       ; get value table for module
  2689.         mov     dl,10[bx+di]    ; get current value
  2690.         shr     bx,1            ; /2 for byte table
  2691.         dec     bx              ; 1->n --> 0->n-1
  2692.         mov     di,offset dgroup:ctrlmap; point to control map
  2693.         mov     [di+bx],dl      ; set new ctrl code
  2694.         jmp     _cancel
  2695. ;==============================================================
  2696. ; MIDI Control mapping
  2697. ; second group of control modules
  2698. ;--------------------------------------------------------------
  2699.  
  2700.         public _mapp   
  2701. _mapp:  test    usrflg,1                ; inputting now
  2702.         jnz     mappx                   ; yes, exit
  2703.         ;
  2704.         mov     bp,si                   ; save si
  2705.         mov     si,6[di]                ; set up for show
  2706.         mov     es,4[di]                ; /
  2707.         mov     bx,offset dgroup:ctrlmpp; point to control map
  2708.         add     si,320                  ; point to 1st value screen location
  2709.         add     di,var0                 ; point to 1st value in module
  2710.         mov     cx,8                    ; # of values
  2711.         ;
  2712. mapp1:  mov     al,[bx]                 ; look at value
  2713.         cmp     al,[di]                 ; same as in module?
  2714.         jz      mapp1a                  ; yes, branch
  2715.         mov     [di],al                 ; no, make same
  2716.         tohex   al                      ; display
  2717.         mov     es:[si],ah              ;  /
  2718.         mov     es:2[si],al             ; /
  2719. mapp1a: inc     bx                      ; next map number
  2720.         add     di,2                    ; next value location
  2721.         add     si,160                  ; next screen location
  2722.         loop    mapp1                   ; do another
  2723.         ;
  2724.         mov     si,bp                   ; restore si
  2725. mappx:  nextx                           ; exit
  2726. ;--------------------------------------------------------------
  2727.         public umapp
  2728. umapp:  pop     ax              ; stack bullshit
  2729.         mov     cmdflg,10       ; set up special routine
  2730.         mov     special,offset umappx
  2731.         jmp     workx           ; on to the next stage
  2732.  
  2733. umappx:
  2734.         mov     bx,holdv        ; get offset to the value
  2735.         mov     di,varsav       ; get value table for module
  2736.         mov     dl,10[bx+di]    ; get current value
  2737.         shr     bx,1            ; /2 for byte table
  2738.         dec     bx              ; 1->n --> 0->n-1
  2739.         mov     di,offset dgroup:ctrlmpp; point to control map
  2740.         mov     [di+bx],dl      ; set new ctrl code
  2741.         jmp     _cancel
  2742. ;==============================================================
  2743. ; MIDI note out.  
  2744. ; All parameters except Velocity are sent when changed. 
  2745. ; Velocity changes are ignored except zero transitions.
  2746. ; When Velocity = 0, a Key-off message is sent with the currently
  2747. ; saved note; the first NZ Velocity seen will send a Key-on message 
  2748. ; with the note value at the input, which gets saved, and the given
  2749. ; velocity level.  While Velocity stays NZ, any change in note values
  2750. ; will cause an immediate Key-off message with the old note, then a
  2751. ; Key on message with the new note, and the latest Velocity value for
  2752. ; that note.
  2753. ;--------------------------------------------------------------
  2754. ; inputs: 
  2755. ;         0: Channel
  2756. ;         1: Hold
  2757. ;         2: Hold AND
  2758. ;         3: Transpose
  2759. ;         4: Transpose
  2760. ;         5: Velocity Offset
  2761. ;         6: Release Value
  2762. ;         7,  9,11,13: Note value
  2763. ;         8, 10,12,14: Velocity
  2764. ;         ---------------------
  2765. ;         15x,16x,17x,18x: saved note
  2766. ;         15+,16+,17+,18+: velocity tick flags
  2767. ;         ---------------------
  2768. ;         outn+1: b7 = initialized flag
  2769. ;         ---------------------
  2770. ;         temp0:  transpose offset
  2771. ;         temp1:  velocity  offset
  2772. ;         temp2:  release value
  2773. ;         temp3:  enable flag
  2774. ;         ---------------------
  2775. ;         dh:     channel
  2776. ;--------------------------------------------------------------
  2777.         public _noteo,_noteo1,_noteo2,_noteo3
  2778. _noteo3:nop
  2779. _noteo2:nop
  2780. _noteo1:nop
  2781. _noteo: 
  2782.         test    byte ptr outn+1[di],80h ; initialized?
  2783.         jnz     noteo1                  ; yes, branch
  2784. ;--------------------------------------------------------------
  2785. ; initialize
  2786. ;--------------------------------------------------------------
  2787.         mov     cx,8                    ; 4 note+velocity inputs
  2788.         mov     bx,0                    ; use for index
  2789. noteo0: mov     byte ptr var15[bp+di],0 ; clear
  2790.         inc     bx                      ; bump index
  2791.         loop    noteo0                  ; loop
  2792.         initv   var2,0ffh               ; Hold mask <- FF
  2793.         mov     byte ptr outn+1[di],80h ; set init flag
  2794.         nextx                           ; ... on to next module 
  2795. ;--------------------------------------------------------------
  2796. ; Get Channel Number
  2797. ;--------------------------------------------------------------
  2798. noteo1: getv    dh,var0                 ; get it
  2799.         mchan   dh                      ; mask & set
  2800.         xchg    outn[di],dh             ; save for next time
  2801.         cmp     outn[di],dh             ; same as last?
  2802.         jnz     noteo2a                 ; no, mute with old
  2803. ;--------------------------------------------------------------
  2804. ; Check for Enable/Mute
  2805. ;--------------------------------------------------------------
  2806.         mov     temp3,0                 ; zip enable flag
  2807.         getv    al,var1                 ; get enable
  2808.         getv    ah,var2                 ; get enable mask
  2809.         and     al,ah                   ; /
  2810.         jz      noteo2a                 ; mute if not enabled
  2811.         mov     al,mprstf               ; stop set
  2812.         or      al,lodflg               ; or load flag
  2813.         jz      noteo2x                 ; branch if no mute
  2814. noteo2a:mov     temp3,1                 ; else set it
  2815. noteo2x:mov     es,4[di]                ; get seg addr
  2816.         mov     bx,6[di]                ; get module screen address
  2817.         dec     bx                      ; point to led
  2818.         test    temp3,1                 ; test for z
  2819.         mov     al,red                  ; set up for z
  2820.         jnz     noteo2b                 ; branch if z
  2821.         mov     al,red+hi               ; else set up for nz
  2822. noteo2b:mov     es:[bx],al              ; set the led
  2823. ;--------------------------------------------------------------
  2824. ; Get note Transpose value
  2825. ;--------------------------------------------------------------
  2826.         getv    al,var3                 ; get it
  2827.         getv    ah,var4                 ; get it
  2828.         add     al,ah                   ; add together
  2829.         mov     temp0,al                ; put it away
  2830. ;--------------------------------------------------------------
  2831. ; Get Velocity offset
  2832. ;--------------------------------------------------------------
  2833.         getv    al,var5                 ; get it
  2834.         mov     temp1,al                ; put it away
  2835. ;--------------------------------------------------------------
  2836. ; Get Release value   
  2837. ;--------------------------------------------------------------
  2838.         getv    al,var6                 ; get it
  2839.         and     al,127                  ; strip msb
  2840.         mov     temp2,al                ; put it away
  2841. ;--------------------------------------------------------------
  2842. ; Key/velocity "A"
  2843. ;--------------------------------------------------------------
  2844.         push    si                      ; save si
  2845.         mov     si,di                   ; use as saved value ptr
  2846.         add     si,var15                ; si = onv, si+1 = vflag
  2847.         mov     bp,4                    ; do 4 of them
  2848.         ;
  2849. noteo4: test    temp3,1                 ; mute?
  2850.         jnz     noteo4a                 ; yes, branch
  2851.         ;
  2852.         getv    ah,var8                 ; get velocity
  2853.         or      ah,ah                   ; is it on?
  2854.         jnz     noteo4b                 ; yes, branch
  2855.         ;
  2856. noteo4a:test    byte ptr 1[si],1        ; was note on
  2857.         jz      noteo4x                 ; no, exit
  2858.         ;
  2859.         mov     al,[si]                 ; yes, turn old note off
  2860.         call    noteoff                 ; /
  2861.         mov     byte ptr 1[si],0        ; zip vflag
  2862.         jmp     noteo4x                 ; exit
  2863.         ; 
  2864. noteo4b:test    byte ptr 1[si],1        ; was note on
  2865.         jnz     noteo4c                 ; yes, branch
  2866.         ;
  2867.         getv    al,var7                 ; get the note
  2868.         add     al,temp0                ; add offset
  2869.         mov     [si],al                 ; save it
  2870.         call    noteon                  ; turn it on
  2871.         mov     byte ptr 1[si],1        ; flag it
  2872.         jmp     noteo4x                 ; exit
  2873.         ;
  2874. noteo4c:getv    al,var7                 ; get the note
  2875.         add     al,temp0                ; add offset
  2876.         cmp     al,[si]                 ; has it changed?
  2877.         jz      noteo4x                 ; no, exit
  2878.         ;
  2879.         xchg    al,[si]                 ; yes, swap new w old
  2880.         call    noteoff                 ; turn old off
  2881.         mov     al,[si]                 ; turn new on
  2882.         call    noteon
  2883.         ;
  2884. noteo4x:
  2885.         add     si,2                    ; bump pointers
  2886.         add     di,4                    ; /
  2887.         dec     bp                      ; dec loop index
  2888.         jnz     noteo4                  ; loop
  2889.         pop     si                      ; restore si
  2890.         nextx
  2891. ;--------------------------------------------------------------
  2892. ; Note On 
  2893. ; call nv in al, v in ah
  2894. ;--------------------------------------------------------------
  2895. Noteon:
  2896.         xchg    al,dh                   ; get channel
  2897.         or      al,090H                 ; MIDI Key-on
  2898.         call    tomidi                  ; send Key-on+channel
  2899.         xchg    al,dh                   ; get nv, restore channel
  2900.         and     al,127                  ; strip msb
  2901.         call    tomidi                  ; send Note value
  2902.         mov     al,ah                   ; get velocity
  2903.         add     al,temp1                ; add offset
  2904.         jns     noteon1                 ; branch if < 128
  2905.         mov     al,127                  ; else make 127
  2906. noteon1:call    tomidi                  ; send Velocity
  2907.         ret                             ; exit
  2908. ;--------------------------------------------------------------
  2909. ; Note Off
  2910. ; call nv in al
  2911. ;--------------------------------------------------------------
  2912. Noteoff:
  2913.         xchg    al,dh                   ; get channel
  2914.         or      al,080H                 ; MIDI Key-off
  2915.         call    tomidi                  ; send Key-off+channel
  2916.         xchg    al,dh                   ; get nv, restore channel
  2917.         and     al,127                  ; strip msb
  2918.         call    tomidi                  ; send Note value
  2919.         mov     al,temp2                ; get release value
  2920.         call    tomidi                  ; send release value
  2921.         ret                             ; exit
  2922. ;==============================================================
  2923. ; MIDI channel output controller
  2924. ;--------------------------------------------------------------
  2925. ; inputs: 
  2926. ;         0: channel
  2927. ;         1: Hold
  2928. ;         2: Program change
  2929. ;         3: After Touch
  2930. ;         4: Pitch Bend
  2931. ;         ---------------------
  2932. ;         5: Volume        (mapo 0)
  2933. ;         6: Mod whl       (mapo 1)
  2934. ;         7: controller A  (mapo 2)
  2935. ;         8: controller B  (mapo 3)
  2936. ;         9: controller C  (mapo 4)
  2937. ;         10:controller D  (mapo 5)
  2938. ;         11:controller 1  (mapo 6)
  2939. ;         12:controller 2  (mapo 7)
  2940. ;         ---------------------
  2941. ;         13x: old program change
  2942. ;         13+: old after touch
  2943. ;         14x: old pitch bend
  2944. ;         15x - 18+: old controller values
  2945. ;         ---------------------
  2946. ;         outn+1: b7 = initialized flag
  2947. ;         ---------------------
  2948. ;         dh:     channel
  2949. ;--------------------------------------------------------------
  2950.         public _chano,_chanl
  2951. _chanl: mov     bp,offset dgroup:ctrlmpp; index for ctrlmap
  2952.         jmp     chanl0                  ; start w 2nd map
  2953. ;--------------------------------------------------------------
  2954. _chano: mov     bp,offset dgroup:ctrlmap; index for ctrlmap
  2955. chanl0: test    byte ptr outn+1[di],80h ; initialized?
  2956.         jnz     chano1                  ; yes, branch
  2957. ;--------------------------------------------------------------
  2958. ; initialize
  2959. ;--------------------------------------------------------------
  2960.         initv   var1,1                  ; Hold   <- 1
  2961.         initv   var4,080h               ; Bend   <- 80H
  2962.         initv   var5,07fh               ; Volume <- 7fH
  2963.         mov     byte ptr outn+1[di],80h ; set init flag
  2964.         ;
  2965. chano0: mov     cx,12                   ; 12 save areas
  2966.         mov     bx,0                    ; use for index
  2967. chano0a:mov     byte ptr var13[bx+di],-1; set to force change
  2968.         inc     bx                      ; bump index
  2969.         loop    chano0a                 ; loop
  2970.         or      clrchf,2                ; setup to clear
  2971. chano0x:
  2972.         nextx                           ; ... on to next module 
  2973. ;--------------------------------------------------------------
  2974. ; Get Channel Number
  2975. ;--------------------------------------------------------------
  2976. chano1: 
  2977.         getv    dh,var0                 ; get it
  2978.         mchan   dh                      ; mask & set
  2979.         test    valflg,-1               ; inputting values?
  2980.         jnz     chano1a                 ; yes, branch out
  2981.         xchg    outn[di],dh             ; save for next time
  2982.         cmp     outn[di],dh             ; same as last?
  2983.         jnz     chano0                  ; no, force change
  2984. chano1a:
  2985. ;--------------------------------------------------------------
  2986. ; Check for Hold
  2987. ;--------------------------------------------------------------
  2988.         getv    al,var1                 ; get hold
  2989.         or      al,mprstf               ; or program reset 
  2990.         or      al,lodflg               ; or load flag
  2991.         or      al,clrchf               ; clear chan flag?
  2992.         jnz     chano1b                 ; yes, force change
  2993.         mov     al,0                    ; clear led flag
  2994. ;--------------------------------------------------------------
  2995. chano1b:mov     es,4[di]                ; get seg addr
  2996.         mov     bx,6[di]                ; get module screen address
  2997.         dec     bx                      ; point to led
  2998.         test    al,-1                   ; test for z
  2999.         jz      chano1c                 ; branch if z
  3000.         mov     byte ptr es:[bx],red    ; clr the led
  3001.         jmp     chano0                  ; reset stuff
  3002. chano1c:mov     byte ptr es:[bx],red+hi ; set the led
  3003. ;--------------------------------------------------------------
  3004. ; Patch Change
  3005. ;--------------------------------------------------------------
  3006.         getv    al,var2                 ; get input value
  3007.         cmp     al,var13[di]            ; any change
  3008.         jz      chano2x                 ; no, branch
  3009.         and     al,7fh                  ; mask
  3010.         mov     var13[di],al            ; yes, store the new value
  3011.         mov     ah,0C0H                 ; MIDI Patch Change
  3012.         or      ah,dh                   ; add in channel info
  3013.         xchg    al,ah                   ; fix
  3014.         call    tomidi                  ; send it to midi
  3015.         xchg    al,ah                   ; fix
  3016.         call    tomidi                  ; send value to midi
  3017. chano2x:
  3018. ;--------------------------------------------------------------
  3019. ; Aftertouch
  3020. ;--------------------------------------------------------------
  3021.         getv    al,var3                 ; get input value
  3022.         cmp     al,var13+1[di]          ; any change
  3023.         jz      chano3x                 ; no, branch
  3024.         and     al,127                  ; strip msb
  3025.         mov     var13+1[di],al          ; yes, store the new value
  3026.         mov     ah,0D0H                 ; MIDI After Touch
  3027.         or      ah,dh                   ; add in channel info
  3028.         xchg    al,ah                   ; fix
  3029.         call    tomidi                  ; send it to midi
  3030.         xchg    al,ah                   ; fix
  3031.         call    tomidi                  ; send value to midi
  3032. chano3x:
  3033. ;--------------------------------------------------------------
  3034. ; Pitch Bend
  3035. ;--------------------------------------------------------------
  3036.         getv    al,var4                 ; get input value
  3037.         cmp     al,var14[di]            ; any change
  3038.         jz      chano5x                 ; no, branch
  3039.         mov     var14[di],al            ; yes, store the new value
  3040. ;       add     al,80h                  ; center for pitch bend
  3041.         shr     al,1                    ; strip lsb
  3042.         rcr     ch,1                    ; put in ch
  3043.         rcr     ch,1                    ; mov into position
  3044.         and     ch,64                   ; clean it up
  3045.         mov     ah,0E0H                 ; MIDI Pitch Bend
  3046.         or      ah,dh                   ; add in channel info
  3047.         xchg    ah,al                   ; fix
  3048.         call    tomidi                  ; send it to midi
  3049.         mov     al,ch                   ; fix
  3050.         call    tomidi                  ; send ls value to midi
  3051.         mov     al,ah                   ; fix
  3052.         call    tomidi                  ; send ms value to midi
  3053. chano5x:
  3054. ;--------------------------------------------------------------
  3055. ; Controllers mapped by mapo module into array: ctrlmap 0-5
  3056. ;--------------------------------------------------------------
  3057.         push    si                      ; save si
  3058.         mov     si,di                   ; use as pointer
  3059.         add     si,var15                ; /
  3060.         mov     cx,6                    ; 6 to do
  3061. chano6:
  3062.         getv    al,var5                 ; get input value
  3063.         cmp     al,[si]                 ; any change
  3064.         jz      chano6a                 ; no, branch
  3065.         and     al,127                  ; strip msb
  3066.         mov     [si],al                 ; yes, store the new value
  3067.         mov     ah,0B0H                 ; MIDI Control Change
  3068.         or      ah,dh                   ; add in channel info
  3069.         xchg    ah,al                   ; fix
  3070.         call    tomidi                  ; send it to midi
  3071.         mov     al,ds:[bp]              ; mapped ctrl number
  3072.         call    tomidi                  ; send it to midi
  3073.         xchg    ah,al                   ; fix
  3074.         call    tomidi                  ; send value to midi
  3075. chano6a:inc     bp                      ; bump pointers
  3076.         inc     si                      ;  /
  3077.         add     di,2                    ; /
  3078.         loop    chano6                  ; loop
  3079. ;--------------------------------------------------------------
  3080. ; Controllers mapped by mapo module into array: ctrlmap 6,7
  3081. ;--------------------------------------------------------------
  3082.         mov     cx,2                    ; 2 to do
  3083. chano7:
  3084.         getv    al,var5                 ; get input value
  3085.         and     al,127                  ; strip msb, test for Z
  3086.         jz      chano7b                 ; branch if Z
  3087.         mov     al,127                  ; else make 127
  3088. chano7b:cmp     al,[si]                 ; any change
  3089.         jz      chano7a                 ; no, branch
  3090.         mov     [si],al                 ; yes, store the new value
  3091.         mov     ah,0B0H                 ; MIDI Control Change
  3092.         or      ah,dh                   ; add in channel info
  3093.         xchg    ah,al                   ; fix
  3094.         call    tomidi                  ; send it to midi
  3095.         mov     al,ds:[bp]              ; mapped ctrl number
  3096.         call    tomidi                  ; send it to midi
  3097.         xchg    ah,al                   ; fix
  3098.         call    tomidi                  ; send value to midi
  3099. chano7a:inc     bp                      ; bump pointers
  3100.         inc     si                      ;  /
  3101.         add     di,2                    ; /
  3102.         loop    chano7                  ; loop
  3103.         ;
  3104.         pop     si                      ; restore si
  3105.         nextx                           ; exit
  3106. ;==============================================================
  3107. ; MIDI event programmer/sequencer
  3108. ; normal output, all inputs are magenta user inputs.            
  3109. ; -- all number inputs use addr+1 to hold output flag copy
  3110. ; inputs:
  3111. ; 0x:   user input to change address
  3112. ; 1x:   end address
  3113. ; 2x:   Undo switch
  3114. ; 2+:   user input flag
  3115. ; 3x:   Store switch
  3116. ; 3+:   initialized flag
  3117. ; 4x:   Recall switch
  3118. ; 4+:   module number
  3119. ; 5x:   Save switch
  3120. ; 6x:   Measures to next (first of sequencer data)
  3121. ; 7x:   stage 1
  3122. ; 8x:   stage 2     
  3123. ; 9x:   stage 3      
  3124. ; 10x:  stage A
  3125. ; 11x:  stage B     
  3126. ; 12x:  stage C
  3127. ; 13x:  stage D
  3128. ; 14x:  stage w slew E
  3129. ; 15x:  slew value for E
  3130. ; 16x:  stage w slew F
  3131. ; 17x:  slew value for F
  3132. ; 18x:  stage w slew G
  3133. ; 19x:  slew value for G
  3134. ; 20x:  stage w slew H
  3135. ; 21x:  slew value for H
  3136. ; slewc: slew value buffer C
  3137. ; slewd: slew value buffer D
  3138. ; slewe: slew value buffer E
  3139. ; slewf: slew value buffer F
  3140. ; pubuf: Undo Buffer
  3141. ; psbuf: Save Buffer
  3142. ;--------------------------------------------------------------
  3143.         public _progo
  3144. _progo: cmp     byte ptr var3+1[di],0abh; initialized?
  3145.         jz      progoii                 ; yes, branch
  3146.         ;
  3147.         mov     cx,98                   ; big mother
  3148.         mov     bx,var0                 ; clear variable space
  3149. progoi: mov     byte ptr [bx+di],0      ; zip it
  3150.         inc     bx                      ; bump address
  3151.         loop    progoi                  ; loop
  3152.         ;
  3153.         mov     al,modnum               ; get module number
  3154.         mov     byte ptr var4+1[di],al  ; save it
  3155.         mov     byte ptr var3+1[di],0abh; set init flag
  3156.         ;
  3157. progoii:test    usrflg,1                ; user input now?
  3158.         jz      progo0                  ; no, branch
  3159.         mov     byte ptr var2+1[di],1   ; yes, set show differences
  3160.         nextx                           ; ...easy exit
  3161. ;--------------------------------------------------------------
  3162. ; process master reset
  3163. ;
  3164. progo0: mov     al,mpadrf               ; address change?
  3165.         or      al,al                   ; /
  3166.         jz      progo0a                 ; no, branch
  3167.         mov     al,mpadr                ; yes, get master address
  3168.         mov     var0[di],al             ; set local address = master
  3169. progo0a:
  3170. ;--------------------------------------------------------------
  3171.         mov     bp,si                   ; save si
  3172.         mov     es,4[di]                ; get screen seg addr
  3173.         mov     si,6[di]                ; get screen ofst addr
  3174. ;--------------------------------------------------------------
  3175.         test    mpmodf,1                ; programming or playing?
  3176.         jz      progo1                  ; branch if playing
  3177.         jmp     progo2                  ; else jump to programming
  3178. ;--------------------------------------------------------------
  3179. ; mode = playing
  3180. ;--------------------------------------------------------------
  3181. ;
  3182. progo1: test    mmstart,1               ; master measure start?
  3183.         jz      progo1b                 ; no, branch
  3184.         cmp     byte ptr var6[di],0     ; local measure count = 0?
  3185.         jz      progo1a                 ; yes, branch
  3186.         dec     byte ptr var6[di]       ; no, count down 1
  3187.         jmp     short progo1b           ; ...on to the next
  3188. ;--------------------------------------------------------------
  3189. ; address change
  3190. ;
  3191. progo1a:mov     al,var1[di]             ; is end <= address
  3192.         cmp     al,byte ptr var0[di]    ; /
  3193.         jbe     progo1b                 ; yes, don't bump address
  3194.         test    mprstf,-1               ; master reset?
  3195.         jnz     progo1b                 ; yes, don't bump address
  3196.         inc     byte ptr var0[di]       ; else bump sequencer address
  3197. progo1b:mov     al,var0[di]             ; has address changed
  3198.         cmp     al,var0+1[di]           ; /
  3199.         jz      progo1c                 ; no, branch
  3200.         putn    al                      ; yes, send it out
  3201.         call    sq_ob                   ; yes copy seq to output buffer
  3202.         mov     byte ptr var2+1[di],1   ; set show differences
  3203.         showpq  0                       ; display address
  3204. progo1c:showpq  6                       ; display measure counter
  3205.         jmp     progo3                  ; branch to common stuff
  3206. ;--------------------------------------------------------------
  3207. ; mode = programming
  3208. ;--------------------------------------------------------------
  3209. ; address change
  3210. ;
  3211. progo2: mov     al,var0[di]             ; has address changed
  3212.         cmp     al,var0+1[di]           ; /
  3213.         jz      progo2a                 ; no, branch
  3214.         putn    al                      ; yes, send it out
  3215.         call    ob_ub                   ; output buf to undo buf
  3216.         call    sq_ob                   ; sequencer to output buf
  3217.         showpq  0                       ; display the new value
  3218.         mov     byte ptr var2+1[di],1   ; set show differences
  3219. progo2a:
  3220. ;--------------------------------------------------------------
  3221. ; measures counter
  3222. ;
  3223.         mov     al,var6[di]             ; measures value changed?
  3224.         cmp     al,var6+1[di]           ; /
  3225.         jz      progo2e                 ; no, branch
  3226.         mov     var6+1[di],al           ; yes, clear flag
  3227.         showpv  6                       ; display measure counter
  3228.         mov     byte ptr var2+1[di],1   ; set show differences
  3229. progo2e:
  3230. ;--------------------------------------------------------------
  3231. ; undo button
  3232. ;
  3233.         test    byte ptr var2[di],1     ; undo button pushed?
  3234.         jz      progo2b                 ; no, branch
  3235.         mov     byte ptr var2[di],0     ; clear the button
  3236.         call    ub_ob                   ; swap undo with output
  3237.         jmp     short progo2z           ; show & tell
  3238. progo2b: 
  3239. ;--------------------------------------------------------------
  3240. ; store button
  3241. ;
  3242.         test    byte ptr var3[di],1     ; store button pushed?
  3243.         jz      progo2c                 ; no, branch
  3244.         mov     byte ptr var3[di],0     ; clear the button
  3245.         call    sq_ub                   ; sequencer to undo buf
  3246.         call    ob_sq                   ; output buffer to seq
  3247. ;       or      _mpab,2                 ; set buffer used flag
  3248.         jmp     short progo2z           ; show & tell
  3249. progo2c:
  3250. ;--------------------------------------------------------------
  3251. ; recall button
  3252. ;                                               
  3253.         test    byte ptr var4[di],1     ; recall button pushed?
  3254.         jz      progo2d                 ; no, branch
  3255.         mov     byte ptr var4[di],0     ; clear the button
  3256.         call    ob_ub                   ; output buf to undo buf
  3257.         call    sb_ob                   ; save buf to out buf
  3258.         jmp     short progo2z           ; show & tell
  3259. progo2d:
  3260. ;--------------------------------------------------------------
  3261. ; save button
  3262. ;
  3263.         test    byte ptr var5[di],1     ; save button pushed?
  3264.         jz      progo2x                 ; no, branch
  3265.         mov     byte ptr var5[di],0     ; clear the button
  3266.         call    ob_sb                   ; output buf to save buf
  3267. ;--------------------------------------------------------------
  3268. progo2z:mov     byte ptr var2+1[di],1   ; set show differences
  3269. progo2x:
  3270. ;--------------------------------------------------------------
  3271. ; common code for programming or playing
  3272. ;--------------------------------------------------------------
  3273. ; process outbyte
  3274. ;
  3275. progo3:
  3276.         mov     al,var7[di]             ; out byte change?
  3277.         cmp     al,var7+1[di]           ; /
  3278.         jz      progo3a                 ; no, jmp to next
  3279.         mov     var7+1[di],al           ; yes, set flag
  3280.         mov     bl,var4+1[di]           ; bx = Channel
  3281.         mov     bh,0                    ; /
  3282.         add     bx,offset dgroup:pcvx   ; point to outval table
  3283.         mov     [bx],al                 ; put value to the table
  3284. progo3a:showpv  7                       ; update display
  3285. ;--------------------------------------------------------------
  3286.         mov     al,var8[di]             ; out byte change?
  3287.         cmp     al,var8+1[di]           ; /
  3288.         jz      progo3b                 ; no, jmp to next
  3289.         mov     var8+1[di],al           ; yes, set flag
  3290.         mov     bl,var4+1[di]           ; bx = Channel
  3291.         mov     bh,0                    ; /
  3292.         add     bx,offset dgroup:pcvy   ; point to outval table
  3293.         mov     [bx],al                 ; put value to the table
  3294. progo3b:showpv  8                       ; update display
  3295. ;--------------------------------------------------------------
  3296.         mov     al,var9[di]             ; out byte change?
  3297.         cmp     al,var9+1[di]           ; /
  3298.         jz      progo3c                 ; no, jmp to next
  3299.         mov     var9+1[di],al           ; yes, set flag
  3300.         mov     bl,var4+1[di]           ; bx = Channel
  3301.         mov     bh,0                    ; /
  3302.         add     bx,offset dgroup:pcvz   ; point to outval table
  3303.         mov     [bx],al                 ; put value to the table
  3304. progo3c:showpv  9                       ; update display
  3305. ;--------------------------------------------------------------
  3306. ; send non-slew output values
  3307. ;
  3308. ;progo4:
  3309. ;--------------------------------------------------------------
  3310.         mov     al,var10[di]            ; out byte change?
  3311.         cmp     al,var10+1[di]          ; /
  3312.         jz      progo4a                 ; no, jmp to next
  3313.         mov     var10+1[di],al          ; yes, set flag
  3314.         mov     bl,var4+1[di]           ; bx = Channel
  3315.         mov     bh,0                    ; /
  3316.         add     bx,offset dgroup:pcva   ; point to outval table
  3317.         mov     [bx],al                 ; put value to the table
  3318. progo4a:showpv  10                      ; update display
  3319. ;--------------------------------------------------------------
  3320.         mov     al,var11[di]            ; out byte change?
  3321.         cmp     al,var11+1[di]          ; /
  3322.         jz      progo4b                 ; no, jmp to next
  3323.         mov     var11+1[di],al          ; yes, set flag
  3324.         mov     bl,var4+1[di]           ; bx = Channel
  3325.         mov     bh,0                    ; /
  3326.         add     bx,offset dgroup:pcvb   ; point to outval table
  3327.         mov     [bx],al                 ; put value to the table
  3328. progo4b:showpv  11                      ; update display
  3329. ;--------------------------------------------------------------
  3330.         mov     al,var12[di]            ; out byte change?
  3331.         cmp     al,var12+1[di]          ; /
  3332.         jz      progo4c                 ; no, jmp to next
  3333.         mov     var12+1[di],al          ; yes, set flag
  3334.         mov     bl,var4+1[di]           ; bx = Channel
  3335.         mov     bh,0                    ; /
  3336.         add     bx,offset dgroup:pcvc   ; point to outval table
  3337.         mov     [bx],al                 ; put value to the table
  3338. progo4c:showpv  12                      ; update display
  3339. ;--------------------------------------------------------------
  3340.         mov     al,var13[di]            ; out byte change?
  3341.         cmp     al,var13+1[di]          ; /
  3342.         jz      progo4d                 ; no, jmp to next
  3343.         mov     var13+1[di],al          ; yes, set flag
  3344.         mov     bl,var4+1[di]           ; bx = Channel
  3345.         mov     bh,0                    ; /
  3346.         add     bx,offset dgroup:pcvd   ; point to outval table
  3347.         mov     [bx],al                 ; put value to the table
  3348. progo4d:showpv  13                      ; update display
  3349. ;--------------------------------------------------------------
  3350. ; send values with slew
  3351. ;
  3352.         mov     bx,slewe                ; point to slew buffer        
  3353.         mov     dx,var14[di]            ; get input & target
  3354.         mov     cl,var15[di]            ; get rate
  3355.         call    pslew                   ; get new slew value
  3356.         cmp     var14[di],dx            ; did it change?
  3357.         mov     var14[di],dx            ; (put it away)
  3358.         jz      progo4e                 ; no change,split
  3359.         ;
  3360.         mov     bl,var4+1[di]           ; bx = Channel
  3361.         mov     bh,0                    ; /
  3362.         add     bx,offset dgroup:pcve   ; point to outval table
  3363.         mov     [bx],dh                 ; put value to the table
  3364.         ;
  3365. progo4e:showpp  14                      ; update display
  3366.         showpq  15                      ; display & flag rate
  3367. ;--------------------------------------------------------------
  3368.         mov     bx,slewf                ; point to slew buffer        
  3369.         mov     dx,var16[di]            ; get input & target
  3370.         mov     cl,var17[di]            ; get rate
  3371.         call    pslew                   ; get new slew value
  3372.         cmp     var16[di],dx            ; did it change?
  3373.         mov     var16[di],dx            ; (put it away)
  3374.         jz      progo4f                 ; no change,split
  3375.         ;
  3376.         mov     bl,var4+1[di]           ; bx = Channel
  3377.         mov     bh,0                    ; /
  3378.         add     bx,offset dgroup:pcvf   ; point to outval table
  3379.         mov     [bx],dh                 ; put value to the table
  3380.         ;
  3381. progo4f:showpp  16                      ; update display
  3382.         showpq  17                      ; display & flag rate
  3383. ;--------------------------------------------------------------
  3384.         mov     bx,slewg                ; point to slew buffer        
  3385.         mov     dx,var18[di]            ; get input & target
  3386.         mov     cl,var19[di]            ; get rate
  3387.         call    pslew                   ; get new slew value
  3388.         cmp     var18[di],dx            ; did it change?
  3389.         mov     var18[di],dx            ; (put it away)
  3390.         jz      progo4g                 ; no change,split
  3391.         ;
  3392.         mov     bl,var4+1[di]           ; bx = Channel
  3393.         mov     bh,0                    ; /
  3394.         add     bx,offset dgroup:pcvg   ; point to outval table
  3395.         mov     [bx],dh                 ; put value to the table
  3396.         ;
  3397. progo4g:showpp  18                      ; update display
  3398.         showpq  19                      ; display & flag rate
  3399. ;--------------------------------------------------------------
  3400.         mov     bx,slewh                ; point to slew buffer        
  3401.         mov     dx,var20[di]            ; get input & target
  3402.         mov     cl,var21[di]            ; get rate
  3403.         call    pslew                   ; get new slew value
  3404.         cmp     var20[di],dx            ; did it change?
  3405.         mov     var20[di],dx            ; (put it away)
  3406.         jz      progo4h                 ; no change,split
  3407.         ;
  3408.         mov     bl,var4+1[di]           ; bx = Channel
  3409.         mov     bh,0                    ; /
  3410.         add     bx,offset dgroup:pcvh   ; point to outval table
  3411.         mov     [bx],dh                 ; put value to the table
  3412.         ;
  3413. progo4h:showpp  20                      ; update display
  3414.         showpq  21                      ; display & flag rate
  3415. ;--------------------------------------------------------------
  3416. ; module execution ends here
  3417. ; clean up & display output value
  3418. ;--------------------------------------------------------------
  3419.         test    byte ptr var2+1[di],1   ; show differences?
  3420.         jz      progo6a                 ; no, branch
  3421.         call    sq?ob                   ; show if ob <> seq
  3422. progo6a:mov     si,bp                   ; restore si
  3423.         mov     byte ptr var2+1[di],0   ; clear user input flag
  3424.         nextv                           ; display output, exit
  3425. ;--------------------------------------------------------------
  3426. ; subroutine to update slew value
  3427. ; call with bx = slew buffer offset (slewc, slewd, etc.)
  3428. ;           dx = input/output (dh), target (dl)
  3429. ;           cl = rate
  3430. ; returns with dx = input/output, target
  3431. ;
  3432. ; formula:
  3433. ;       initialize:
  3434. ;               input * 256 --> sum; input --> output
  3435. ;       thereafter until sum/256 = target:
  3436. ;               sum - input + target --> sum
  3437. ;               sum/256              --> output
  3438. ;
  3439. ; buffer offsets for values:
  3440. ;       0: sum
  3441. ;       2: saved input
  3442. ;       3: saved target
  3443. ;       4: saved rate
  3444. ;       5: busy
  3445. ;--------------------------------------------------------------
  3446. pslew:  test    byte ptr 5[bx+di],1     ; busy?
  3447.         jnz     pslewa                  ; yes, branch
  3448.         cmp     dl,dh                   ; no, see if target=output
  3449.         jnz     pslewb                  ; not equal, go slew
  3450.         cmp     dh,2[bx+di]             ; else see if input has changed
  3451.         jz      pslewx                  ; exit if no change                
  3452.         ;
  3453. pslewb: mov     3[bx+di],dl             ; save target
  3454.         mov     2[bx+di],dh             ; save input
  3455.         mov     4[bx+di],cl             ; save rate
  3456.         ;
  3457.         mov     dh,dl                   ; target --> output
  3458.         or      cl,cl                   ; rate = 0?
  3459.         jz      pslewx                  ; yes, just exit
  3460. ;        test    mpmodf,1                ; programming or playing?
  3461. ;        jnz     pslewx                  ; just exit if programming
  3462.         mov     byte ptr 5[bx+di],1     ; else flag busy
  3463. ;
  3464.         mov     al,2[bx+di]             ; ax = input * 128
  3465.         mov     ah,0                    ;   /
  3466.         mov     cl,7                    ;  /
  3467.         shl     ax,cl                   ; /
  3468. ;        mov     ah,2[bx+di]             ; ax = input * 256
  3469. ;        mov     al,0                    ; /
  3470.         mov     [bx+di],ax              ; set new sum
  3471.         mov     dh,2[bx+di]             ; input --> output
  3472.         jmp     short pslewx            ; exit
  3473.         ;
  3474. pslewa: dec     byte ptr 4[bx+di]       ; countdown 
  3475.         jnz     pslewx                  ; /
  3476.         or      cl,cl                   ; rate set to 0?
  3477.         jnz     pslewc                  ; no, go on
  3478.         mov     dh,dl                   ; yes, set output=target
  3479.         jmp     short pslewz            ; exit finished
  3480.         ;
  3481. pslewc: mov     4[bx+di],cl             ; save rate count
  3482.         mov     ax,[bx+di]              ; ax = sum
  3483.         mov     cl,2[bx+di]             ; cx = input
  3484.         mov     ch,0                    ; /
  3485.         sub     ax,cx                   ; ax = sum - input
  3486.         mov     cl,3[bx+di]             ; cx = target
  3487.         add     ax,cx                   ; ax = sum - input + target
  3488.         mov     [bx+di],ax              ; save new sum
  3489.         mov     cl,7                    ; ax = new sum / 128
  3490. ;
  3491.         shr     ax,cl                   ; /
  3492.         mov     dh,al                   ; dh = new sum / 128
  3493. ;        mov     dh,ah                   ; dh = new sum / 256
  3494. pslewz: cmp     dh,dl                   ; output = target
  3495.         jnz     pslewx                  ; no, exit
  3496.         mov     byte ptr 5[bx+di],0     ; yes, flag not busy
  3497.         ;
  3498. pslewx: ret                             ; exit
  3499. ;--------------------------------------------------------------
  3500. ; subroutines to copy sequencer buffers
  3501. ;
  3502. ; ob_sb = obuf --> sbuf = output buffer to save buffer
  3503. ; ob_ub = obuf --> ubuf = output buffer to undo buffer
  3504. ; ob_sq = obuf --> seq  = output buffer to sequencer
  3505. ; sb_ob = sbuf --> obuf = save buffer to output buffer
  3506. ; sq_ob = seq  --> obuf = sequencer to output buffer
  3507. ; sq_ub = seq  --> ubuf = sequencer to undo buffer
  3508. ; ub_ob = ubuf <-> obuf = undo buffer swapped with output buffer
  3509. ; sq?ob = show red if sq <> ob, else show yellow
  3510. ;--------------------------------------------------------------
  3511. ; ob_sb = obuf --> sbuf = output buffer to save buffer
  3512. ;
  3513. ob_sb:  mov     bx,di           ; use bx for sbuf addr
  3514.         add     bx,psbuf        ; bx = sbuf addr
  3515.         jmp     short ob_ub0    ; go do it
  3516. ;--------------------------------------------------------------
  3517. ; ob_ub = obuf --> ubuf = output buffer to undo buffer
  3518. ;
  3519. ob_ub:  mov     bx,di           ; use bx for sbuf addr
  3520.         add     bx,pubuf        ; bx = ubuf addr
  3521.         ;
  3522. ob_ub0: mov     si,di           ; get offset to obuf
  3523.         add     si,var6         ; /
  3524.         ;
  3525.         mov     cx,16           ; 16 in a loop
  3526. ob_ubl: mov     al,[si]         ; get obuf byte
  3527.         mov     [bx],al         ; put it away
  3528.         inc     bx              ; bump pointers
  3529.         add     si,2            ; /
  3530.         loop    ob_ubl          ; loop til done
  3531.         ;
  3532.         mov     si,6[di]        ; get screen ofst addr
  3533.         ret
  3534. ;--------------------------------------------------------------
  3535. ; ob_sq = obuf --> seq  = output buffer to sequencer
  3536. ;
  3537. ob_sq:  mov     ah,var4+1[di]   ; offset for channel
  3538.         mov     al,0            ; /
  3539.         add     ax, seg bufpa   ; base seg of seq buffer
  3540.         mov     es,ax           ; es = seg addr of seq buf
  3541.         mov     al,var0[di]     ; get seq step
  3542.         mov     bl,16           ; bump up
  3543.         mul     bl              ; ax = seq addr
  3544.         mov     bx,ax           ; es:bx = seq addr
  3545.         ;
  3546.         mov     si,di           ; get offset to obuf
  3547.         add     si,var6         ; /
  3548.         ;
  3549.         mov     cx,16           ; 16 in a loop
  3550. ob_sql: mov     al,[si]         ; get buffer byte
  3551.         mov     es:[bx],al      ; put to sequencer
  3552.         inc     bx              ; bump pointers
  3553.         add     si,2            ; /
  3554.         loop    ob_sql          ; loop til done
  3555.         ;
  3556.         mov     es,4[di]        ; restore screen seg addr
  3557.         mov     si,6[di]        ; get screen ofst addr
  3558.         ret
  3559. ;--------------------------------------------------------------
  3560. ; sb_ob = sbuf --> obuf = save buffer to output buffer
  3561. ;
  3562. sb_ob:  mov     bx,di           ; use bx for sbuf addr
  3563.         add     bx,psbuf        ; bx = sbuf addr
  3564.  
  3565.         mov     si,di           ; get offset to obuf
  3566.         add     si,var6         ; /
  3567.         ;
  3568.         mov     cx,16           ; 16 in a loop
  3569. sb_obl: mov     al,[bx]         ; get sbuf byte
  3570.         mov     [si],al         ; put to obuf
  3571.         inc     bx              ; bump pointers
  3572.         add     si,2            ; /
  3573.         loop    sb_obl          ; loop til done
  3574.         ;
  3575.         mov     si,6[di]        ; get screen ofst addr
  3576.         ret
  3577. ;--------------------------------------------------------------
  3578. ; sq_ob = seq  --> obuf = sequencer to output buffer
  3579. sq_ob:  mov     ah,var4+1[di]   ; offset for channel
  3580.         mov     al,0            ; /
  3581.         add     ax,seg bufpa    ; base seg of seq buffer
  3582.         mov     es,ax           ; es = seg addr of seq buf
  3583.         mov     al,var0[di]     ; get seq step
  3584.         mov     bl,16           ; bump up
  3585.         mul     bl              ; ax = seq addr
  3586.         mov     bx,ax           ; es:bx = seq addr
  3587.         ;
  3588.         mov     si,di           ; get offset to obuf
  3589.         add     si,var6         ; /
  3590.         ;
  3591.         mov     cx,16           ; 16 in a loop
  3592. sq_obl: mov     al,es:[bx]      ; get the byte
  3593.         mov     [si],al         ; put it away
  3594.         inc     bx              ; bump pointers
  3595.         add     si,2            ; /
  3596.         loop    sq_obl          ; loop til done
  3597.         ;
  3598.         mov     es,4[di]        ; restore screen seg addr
  3599.         mov     si,6[di]        ; get screen ofst addr
  3600.         ret
  3601. ;--------------------------------------------------------------
  3602. ; sq_ub = seq  --> ubuf = sequencer to undo buffer
  3603. ;
  3604. sq_ub:  mov     ah,var4+1[di]   ; offset for channel
  3605.         mov     al,0            ; /
  3606.         add     ax, seg bufpa   ; base seg of seq buffer
  3607.         mov     es,ax           ; es = seg addr of seq buf
  3608.         mov     al,var0[di]     ; get seq step
  3609.         mov     bl,16           ; bump up
  3610.         mul     bl              ; ax = seq addr
  3611.         mov     bx,ax           ; es:bx = seq addr
  3612.         ;
  3613.         mov     si,di           ; use si for sbuf addr
  3614.         add     si,pubuf        ; si = ubuf addr
  3615.         ;
  3616.         mov     cx,16           ; 16 bytes to move
  3617. sq_ubl: mov     al,es:[bx]      ; get seq byte
  3618.         mov     [si],al         ; put it in ubuf
  3619.         loop    sq_ubl          ; loop til done
  3620.         ;
  3621.         mov     es,4[di]        ; restore screen seg addr
  3622.         mov     si,6[di]        ; get screen ofst addr
  3623.         ret
  3624. ;--------------------------------------------------------------
  3625. ; ub_ob = ubuf <-> obuf = undo buffer swapped with output buffer
  3626. ;
  3627. ub_ob:  mov     bx,di           ; use bx for sbuf addr
  3628.         add     bx,pubuf        ; bx = ubuf addr
  3629.         ;
  3630.         mov     si,di           ; get offset to obuf
  3631.         add     si,var6         ; /
  3632.         ;
  3633.         mov     cx,16           ; 16 in a loop
  3634. ub_obl: mov     al,[si]         ; get obuf byte
  3635.         xchg    [bx],al         ; put it away
  3636.         mov     [si],al         ; swap
  3637.         inc     bx              ; bump pointers
  3638.         add     si,2            ; /
  3639.         loop    ub_obl          ; loop til done
  3640.         ;
  3641.         mov     si,6[di]        ; get screen ofst addr
  3642.         ret
  3643.  
  3644. ;--------------------------------------------------------------
  3645. ; sq?ob show red for each of the 16 values when sq <> ob, 
  3646. ; else show yellow
  3647. sq?ob:  mov     ah,var4+1[di]   ; offset for channel
  3648.         mov     al,0            ; /
  3649.         add     ax, seg bufpa   ; base seg of seq buffer
  3650.         mov     es,ax           ; es = seg addr of seq buf
  3651.         mov     cx,ax           ; cx = copy of above
  3652.         mov     al,var0[di]     ; get seq step
  3653.         mov     bl,16           ; bump up
  3654.         mul     bl              ; ax = seq addr
  3655.         mov     bx,ax           ; es:bx = seq addr
  3656.         ;
  3657.         mov     si,di           ; get offset to obuf
  3658.         add     si,var6         ; ds:si = offset to obuf
  3659.         ;
  3660.         push    bp              ; save current bp
  3661.         mov     bp,ds:4[di]     ; bp = screen seg
  3662.         mov     dx,6[di]        ; dx = screen address
  3663.         add     dx,160*6+480    ; dx = offset to var6
  3664.         dec     dx              ; back up to point to label
  3665.         xchg    dx,di           ; di = offset to var6
  3666.         ;                       ; dx = old di (save)
  3667.         mov     ah,16           ; 16 in a loop
  3668. sq?obl: mov     al,es:[bx]      ; get the byte at var
  3669.         cmp     [si],al         ; same
  3670.         mov     al,yellow       ; pretend it is
  3671.         jz      sq?ob2          ; yes, branch
  3672.         mov     al,red
  3673. sq?ob2: mov     es,bp           ; get screen seg
  3674.         mov     es:[di],al      ; set color
  3675.         mov     es,cx           ; seq seg
  3676.         inc     bx              ; bump pointers
  3677.         add     si,2            ;  /
  3678.         add     di,160          ; /
  3679.         dec     ah              ; loop til done
  3680.         jnz     sq?obl          ; /
  3681.         ;
  3682.         pop     bp              ; restore bp
  3683.         mov     di,dx           ; restor variable indes
  3684.         mov     es,4[di]        ; restore screen seg addr
  3685.         mov     si,6[di]        ; get screen ofst addr
  3686.         ret
  3687. ;--------------------------------------------------------------
  3688. ; process magenta inputs
  3689. ;
  3690.         public  uprogo
  3691. uprogo: pop     ax                      ; stack bullshit
  3692.         mov     di,varsav               ; get value table for module
  3693.         cmp     magflg,0                ; no-value?
  3694.         jnz     uprogb                  ; no, branch
  3695.         mov     bx,holdv                ; get offset to the value
  3696.         xor     byte ptr 10[bx+di],1    ; flip value of input
  3697. uprogr: jmp     _cancel                 ; exit
  3698.         ;
  3699. uprogb: mov     cmdflg,10               ; set up special routine
  3700.         mov     special,offset uprogr   ; data exit
  3701.         jmp     workx                   ; on to the next stage
  3702. ;==============================================================
  3703. ; beep a note on the pc speaker
  3704. ; inputs: 0: gate, 1: pitch, 2x: note flags
  3705. ; output: gate
  3706. ;--------------------------------------------------------------
  3707.         public _bopo
  3708. _bopo:  
  3709.         test    mprstf,-1       ; stopped?
  3710.         jz      bopogo          ; no, go on
  3711.         call    toneoff         ; yes, turn off the speaker
  3712.         jmp     bopox           ; exit
  3713.  
  3714. bopogo: getv    al,var0         ; get the gate
  3715.         mov     dl,var2[di]     ; dl = on/off flags
  3716.         or      al,al           ; gate on?
  3717.         jz      bopo1           ; no, branch
  3718.         and     dl,offlg xor -1 ; yes, clear off flag
  3719.         test    dl,onflg        ; is on flag set?
  3720.         jz      bopo2           ; no, branch
  3721. bopo3:
  3722.         mov     di,2[si]        ;; set di pointing to variable list
  3723.         nextx                   ; yes, easy exit
  3724. bopo2:  or      dl,onflg        ; no, set on flag
  3725.         mov     var2[di],dl     ; put it away
  3726. ;--------------------------------------------------------------
  3727. ; note on
  3728.         getv    al,var1         ; get the pitch
  3729.         call    pitch           ; play it
  3730.         mov     cx,dx           ;     /
  3731.         call    toneset         ;   /
  3732.         call    toneon          ; /
  3733.         mov     ah,-1           ; load True
  3734.         putn    ah              ; flag to the output
  3735.         jmp     short bopox
  3736. ;--------------------------------------------------------------
  3737. bopo1:  and     dl,onflg xor -1 ; clock is off, clear on flag
  3738.         test    dl,offlg        ; off flag set?
  3739.         jnz     bopo3           ; yes, easy exit
  3740.         or      dl,offlg        ; no, set the off flag
  3741.         mov     var2[di],dl     ; put it away
  3742.         call    toneoff         ; turn off the note
  3743.         mov     ah,0            ; load False
  3744.         putn    ah              ; flag to the output
  3745. bopox:
  3746.         mov     di,2[si]        ;; set di pointing to variable list
  3747.         nextx                   ; exit
  3748. ;--------------------------------------------------------------
  3749. ; play tones on the pc speaker
  3750. ;
  3751. ;--------------------------------------------------------------
  3752. ; initialize timer chip
  3753. ; Just called once
  3754. ;
  3755. toneinit:
  3756. ;        mov     al,2*40h+3*10h+3*2
  3757. ;        out     43h,al
  3758.         ret
  3759. ;--------------------------------------------------------------
  3760. ; convert from frequency to period
  3761. ; input: frequency in CX
  3762. ; output: period in CX
  3763. ;
  3764. freq:   push    dx
  3765.         push    ax
  3766.         ;
  3767.         mov     dx,12H
  3768.         mov     ax,34deh
  3769.         div     cx
  3770.         mov     cx,ax
  3771.         ;
  3772.         pop     ax
  3773.         pop     dx
  3774.         ret
  3775. ;--------------------------------------------------------------
  3776. ; convert from a pitch to a number
  3777. ; input: pitch number in al
  3778. ; output: value for TONESET in DX
  3779. ;--------------------------------------------------------------
  3780. pitch:  push    cx
  3781.         push    bx
  3782.         push    ax
  3783.         ;
  3784.         mov     ah,0
  3785.         mov     cl,12
  3786.         div     cl
  3787.         ;
  3788.         mov     dl,al
  3789.         mov     al,ah
  3790.         cbw
  3791.         sal     ax,1
  3792.         mov     bx,ax
  3793.         mov     cx,notes[bx]
  3794.         call    freq
  3795.         ;
  3796.         xchg    cx,dx
  3797.         neg     cl
  3798.         add     cl,8
  3799.         sal     dx,cl
  3800.         ;
  3801.         pop     ax
  3802.         pop     bx
  3803.         pop     cx
  3804.         ret
  3805. ;--------------------------------------------------------------
  3806. ; select a tone
  3807. ; input: tone in CX
  3808. ; output: none
  3809. ;
  3810. toneset:push    ax
  3811.         ;
  3812.         mov     al,cl
  3813.         out     42h,al
  3814.         jmp     short $+2
  3815.         mov     al,ch
  3816.         out     42h,al
  3817.         ;
  3818.         pop     ax
  3819.         ret
  3820. ;--------------------------------------------------------------
  3821. ; turn tone on
  3822. ;
  3823. toneon: push    ax
  3824.         in      al,61H
  3825.         or      al,3
  3826.         out     61h,al
  3827.         pop     ax
  3828.         ret
  3829. ;--------------------------------------------------------------
  3830. ; turn tone off
  3831. ;
  3832. toneoff:push    ax
  3833.         in      al,61h
  3834.         and     al,0fch
  3835.         out     61h,al
  3836.         pop     ax
  3837.         ret
  3838. ;==============================================================
  3839. ; pushbutton routine
  3840. ; output is turned on/off every other push
  3841. ; input is set only by user routine
  3842. ;--------------------------------------------------------------
  3843.         public _pusha
  3844. _pusha:
  3845.         nextl                   ; exit
  3846. ;--------------------------------------------------------------
  3847.         public  upusha
  3848. upusha: mov     di,varsav       ; point to variable list
  3849.         xor     byte ptr 8[di],1; flip the output
  3850.         pop     ax              ; keep stack right
  3851.         jmp     _cancel         ; return clean
  3852. ;==============================================================
  3853. ; pushbutton routine
  3854. ; output is a single strobe, lasting from start of loop to priority.
  3855. ; input is set only by user routine
  3856. ;--------------------------------------------------------------
  3857.         public _pushb
  3858. _pushb: 
  3859.         nextt
  3860. ;--------------------------------------------------------------
  3861.         public  upushb
  3862. upushb: mov     di,varsav       ; point to variable list
  3863.         mov     byte ptr 8[di],1; set hi
  3864.         pop     ax              ; keep stack right
  3865.         jmp     _cancel         ; return clean
  3866. ;==============================================================
  3867. ; pushbutton routine
  3868. ; output is incremented/decremented every push, depending on
  3869. ; cursor location on magenta pad. 
  3870. ; input is set only by user routine
  3871. ;--------------------------------------------------------------
  3872.         public _pushc
  3873. _pushc: nextv                           ; update screen
  3874. ;--------------------------------------------------------------
  3875.         public  upushc
  3876. upushc: pop     ax                      ; stack bullshit
  3877.         cmp     magflg,1                ; inc/dec?
  3878.         jnz     upushc1                 ; no, branch
  3879.         ;
  3880.         mov     di,varsav               ; get value table for module
  3881.         mov     ax,curadr               ; up or down button?
  3882.         cmp     ax,cmdloc               ; if same, it's up
  3883.         jz      upushc2                 ; branch if same
  3884.         dec     byte ptr outn[di]       ; dec output value
  3885.         jmp     _cancel                 ; exit
  3886. upushc2:inc     byte ptr outn[di]       ; inc output value
  3887.         jmp     _cancel                 ; exit
  3888.  
  3889. upushc1:mov     cmdflg,10               ; set up special routine
  3890.         mov     special,offset upushc3  ; data exit
  3891.         jmp     workx                   ; exit
  3892.  
  3893. upushc3:mov     di,varsav               ; get value table
  3894.         mov     al,byte ptr var0[di]    ; get new value
  3895.         mov     byte ptr outn[di],al    ; send it out
  3896.         jmp     _cancel                 ; exit
  3897. ;==============================================================
  3898. ; Exit routine for modules that use msb of output byte.
  3899. ; It displays output value, then executes the next module on the list.
  3900. ; assumes di has been set to variable table
  3901. ;
  3902. next:   mov     es,4[di]        ; get seg addr
  3903.         mov     bx,6[di]        ; get module screen address
  3904.         mov     al,8[di]        ; get output value
  3905.         tohex                   ; convert to hex word
  3906.         mov     es:320[bx],ah   ; put to the screen
  3907.         mov     es:322[bx],al   ; /
  3908.         nextx                   ; easy exit
  3909. ;--------------------------------------------------------------
  3910. ; Just execute the next module on the list.
  3911. ;
  3912.         public _dummy
  3913. _dummy: nextx                   ; easy exit
  3914.  
  3915. ;--------------------------------------------------------------
  3916. ; this code converts in-line macros to jumps at the end of modules
  3917. ;
  3918.         public  _nextv,_nextx,_nextl,_nextt
  3919. _nextv: @nextv
  3920. _nextx: @nextx
  3921. _nextl: @nextl
  3922. _nextt: @nextt
  3923. ;==============================================================
  3924. ; user input routines for magenta inputs
  3925. ;
  3926. ;--------------------------------------------------------------
  3927.         public ugatel
  3928. ugatel: pop     ax
  3929.         jmp     _cancel
  3930. ;==============================================================
  3931. _TEXT   ENDS
  3932.         END
  3933.  
  3934.