	TITLE	Main Work Loop for Modular Sequencer
	NAME	MB
	.SALL
;==============================================================
; MusicBox Modular Sequencer, Version 2
; main module
;--------------------------------------------------------------
; author: John Dunn
; date:   03/07/86
; update: 03/20/88
;--------------------------------------------------------------
; COPYRIGHT (C) 1986 John Dunn, All Rights Reserved 
; Entered into the Public Domain, March 20, 1988
;
; Use and copying of this software and preparation of derivative works
; based upon this software are permitted.  Any distribution of this
; software or derivative works must comply with all applicable United
; States export control laws.
; 
; This software is made available AS IS, and the author makes no warranty 
; about the software, its performance, or its conformity to any specification.
; 
; Any person obtaining a copy of this software is requested to send their
; name and address address to:
;
;       John Dunn, Senior Research Fellow
;       Time Arts Inc.
;       3436 Mendocino Ave.
;       Santa Rosa, CA 95401
;
;==============================================================
        include	order.asm
;--------------------------------------------------------------
        include equates.asm
        clkadr  equ 146+(23*160) ; addr of page 0 clock
;==============================================================
        include	macros.asm
;==============================================================
; MACROS
;--------------------------------------------------------------
; convert character x,y to an address
; call with al = video y, bx = video x
; (x= 0-79, y= 0=24)
; returns with bx = offset, ax trashed
;  
vxyadr  macro
        mov     ah,160
        mul     ah
        add     bx,bx
        add     bx,ax
        endm
;--------------------------------------------------------------
; display priority number
;
showp   macro
        and     ah,1                    ;; do ms byte
        xor     ah,1
        add     ah,0f8h
        mov     byte ptr es:158[bx],ah  ;; set high byte
        tohex                           ;; binary to hex
        mov     byte ptr es:160[bx],ah  ;; set the priority
        mov     byte ptr es:162[bx],al  ;; /
        endm
;==============================================================
        if not withc
STACK   SEGMENT para stack 'STACK'
        db 512 dup (?)
STACK   ENDS
        endif
;==============================================================
BUFFV   SEGMENT
        db 0
        db 4094 dup (?) ; video "foo" buffer
        db 0
BUFFV   ENDS
;==============================================================
_DATA   SEGMENT
        ASSUME DS:DGROUP, CS:_TEXT
;--------------------------------------------------------------
        extrn  mute:word,mutef:byte,midisf:byte,midixsf:byte
        extrn  vartbl:near,modscr:near
        extrn  _chrtbl:near
        extrn  _exetbl:near
        extrn  @dummy:near
        extrn  _modsrc:near
        extrn  $menu:near      ; page #'s and menu
        extrn  $dummy:near     ; 25 line dummy for module text buffer
        extrn  _modtxt:near,?modtxt:near
        extrn  @zero:near
        extrn   mmreset:byte,mmstart:byte
        extrn   mmtick:word,mmcount:word,mclocks:word
        extrn   mvlsav:near,mvlnum:abs
        extrn   mprstf:byte
;--------------------------------------------------------------
        extrn   midip:byte
;--------------------------------------------------------------
        public varsav,cmdflg,special,cmdloc,vpage,locsav,curadr,noop
        public ticka,tickis,cmdcnt,valflg,usrflg,magflg,holdv,colr,doesc
        public _tmpfn,_savfn,_lodfn,_bakfn,_mpab,_header,fastflg,modnum
        public lodflg,clrchf,midiok,curonf,asensf
;--------------------------------------------------------------
_bases  dw      0               ; base seg is saved here
clrchf  db      0               ; clear channel flag, used by chanl
tickis  db      0               ; timer value after modules
lodflg  db      0               ; nz for 2 clocks after loading
fastflg db      0               ; nz = fast as possible loops
savtime dw      0               ; place to save time of day
timecnt db      8               ; time count for colon flash
midiss  db      0               ; place to save last midi xtrn sync
waiting db      0               ; nz if waiting on timer
pdf     db      0               ; pd values set by interrupt
pdx     db      39              ;  /
pdy     db      12              ; /
curonf  db      0               ; nz = don't restore screen char
curflg  db      0               ; z to display normal cursor
curcol  db      017h            ; 0 = cursor not being displayed
curdata dw      0               ; data under the cursor
savcol  db      0               ; /
colr    db      blue            ; current number readout color 
vpage   dw      0B800H          ; current video page seg
vpagen  db      0               ; current video page number
vpagep  db      0               ; previous video page number
curadr  dw      1998            ; cursor address offset
execur  dw      0               ; z = don't do it
modchar dw      offset dgroup:$dummy; current module char list
cmdcol  db      0               ; command color
cmdcnt  db      0               ; command count
cmdptr  dw      offset dgroup:@dummy; command pointer
cmdloc  dw      0               ; command location offset
cmdtag  dw      0               ; command label offset
shosav  dw      0               ; place to save it
shoflg  db      0               ; nz = showing output-inputs
cmdflg  db      0               ; nz = a command is pending
magflg  db      0               ; 0=no-value, 1=channel #, 2=input value
errflg  db      0               ; 1 = write, 2 = non-fatal read 
errwrd  dw      0               ; dos error word
byemsg  dw      0               ; addr of exit msg, or 0
room    db      0               ; disk room, in save files
tmpsav  dw      offset dgroup:vartbl; place to hold a variable ptr (move)
                                ; or modsrc addr (reincarnate)
locsav  dw      0               ; place to hold cmdloc, to remember hilights
modnum  db      0               ; module number *2 of last new module
special dw      noop            ; place to hold exe addr of special routine
usrflg  db      0               ; nz when special magenta input is happening
valflg  db      0               ; nz when blue value input is happening
mickx   dw      0               ; current mickey horiz count
lastx   db      0               ; place to save last pdx for no-button cmds
lasty   db      0               ; place to save last pdy for no-button cmds
holdv   dw      0               ; place to hold last value offset 
doesc   dw      noop            ; do this when ESC is selected
cscale  db      'C:C#D:D#E:F:F#G:G#A:A#B:'
diradr  dw      0               ; temp storage for screen directory
dirptr  dw      0               ; last directory file name pointer
_mpab   db      8Fh             ; file load flags
asensf  db      1               ; active sensing send flag
;==============================================================
; the following are constants that may be changed either before
; assembley or with debug after MB.EXE is built.  Actual number of 
; bytes must remain the same, or previously saved files will be 
; incompatable, causing upredictable results when loaded.
;
usesf   db      1                   ; 1 = use _scrfn file if found
midiok  db      1                   ; 0= off, 1= 1 MPU, 3= 2 MPU's
_numpg  dw      3                   ; number of video pages -1 (1/3/7)
                                    ; should be 3 for CGA, 7 for EGA/VGA
_scrfn  db      'tutor.scr',0,0,0,0 ; screen file name
                                    ; if not found, uses screen image
                                    ; from MODSCR, last section of MBV.ASM
_tmpfn  db      '\undo.mb$',0,0,0,0 ; file name for set/undo
                                    ; 0 in 1st byte disables    
_bakfn  db      'previous.mb ',0    ; file name for backup
                                    ; 0 in 1st byte disables    
_lodfn  db      'temp.mb ',0,0,0,0,0; file name for dir loading
_dirfn  db      '*.mb ',0           ; directory file name                   
;==============================================================
_inbuf  db      128 dup (?)         ; kbd input buffer  
_err_wp db      7,'Write Protect: Retry Ignore Quit$'
_err_dx db      7,'Disk Error: Retry Ignore Quit?  $'
_errwx  db      7,'Write Error: Retry Escape Quit? $'
_errwr  db      7,'Write Error: Retry Ignore Quit? $'
_errver db      7,'Wrong Vers: M disabled. Escape? $'

_noundo db      7,'Error in writing to Undo File.$'
_opundo db      7,'Error in opening Undo File.$'
_errmod db      7,'Error in reading modules.  $'
roomis  db      "Room= 20$"
;--------------------------------------------------------------
; header format (only first 128 bytes are actually used)
; byte 0 = revision
; byte 1 = version
; byte 2 = encoding (0 = no encoding in this version)
; byte 3 = 0
; byte 4-43 = copyright notice
; other bytes unused
;--------------------------------------------------------------
_header db      version,release ; version/release word
        db      0,0             ; encoding = 0 = none
        db      'MusicBox Copyright (c) 1986, 1987 John Dunn'
        db      100 dup (0)     ; more stuff
_foo    db      128 dup (?)     ; scratch area
;--------------------------------------------------------------
; the following are saved/loaded
;
valsav  equ     $               ; start of values to save
_savfn  db      'temp.mb ',0,0,0,0,0; file name for saving
ticka   db      0CH             ; timer tick (1456/mtempo)
varptr  dw      offset dgroup:vartbl; addr of next free variable space
varnow  dw      offset dgroup:vartbl; current variable table addr
varsav  dw      offset dgroup:vartbl; saved variable table addr
last    dw      0               ; index of last module in exetbl
                                ; also next module's priority
valend  equ     $               ; end of values to save
_DATA   ENDS
;==============================================================
_TEXT   SEGMENT
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: NOTHING
;--------------------------------------------------------------
        public  loops
loops   dw      0               ; module loop count
;--------------------------------------------------------------
        extrn _dummy:near
        extrn ticks:word,timer:word,midixs:byte
        extrn startm:near,stopm:near,startt:near,stopt:near
        extrn sendm:near,alloff:near,tomidi:near
        extrn allclr:near,allmidi:near
        extrn secondf:byte,seconds:word
;==============================================================
; main body of program
;--------------------------------------------------------------
; initialization
;
        public  _doit
_doit:
        if      withc           ; if compiled with C
        push    es              ; save C regs
        push    bp              ;     /
        push    si              ;   /
        push    di              ; /
        else                    ; else if assembly
        mov     ax,seg dgroup   ; set data seg
        mov     dx,ds           ; save initial data seg
        mov     ds,ax           ;  /
        mov     _bases,dx       ; /
        endif
        ;
        mov     ah,25H          ; set int vect
        mov     al,24H          ; int 24h for MS crit error
        push    ds              ; save data seg
        mov     dx,cs           ; get code ds
        mov     ds,dx           ; point to cerror
        mov     dx,offset cerror; vector to mine
        int     21H             ; set new int vect
        pop     ds              ; restore data seg
        ;
        mov     cx,_numpg       ; get number of pages
        inc     cx              ; +1 for loop
        if      debug           ; if debug mode, don't clr page 7
        dec     cx              ;           /
        endif                   ;          /
        mov     al,0            ;         /
start0: push    cx              ;        /
        push    ax              ;       /
        call    page            ;      /
        call    clx             ;     /
        pop     ax              ;    /   
        inc     al              ;   /
        pop     cx              ;  /
        loop    start0          ; /
        mov     al,0            ; set page 0 active
        call    page            ; /
        call    shoall          ; show all modules
        call    modloc          ; set module location addresses
        ;
        call    savmod          ; save undo modules
        ;
        call    getfn           ; get file name from cmd line
        jnc     start1          ; branch if no input filename
        ;
        mov     ah,3dh          ; dos open file command
        mov     al,0            ; read only
        mov     dx,offset dgroup:_savfn; point to file name
        int     21H             ; open the file
        jc      start1          ; branch if open error
        call    lodmod0         ; else load modules
        call    showfn          ; show the save filename
        call    getdir          ; show directory enterys
        call    dopath          ; show current path
        call    dompab          ; show mpad status
        call    menus           ; draw menus
        mov     vpagen,0        ; set up for swaps
        mov     al,1            ; show page 1
        call    page            ;  /       
        jmp     short start2    ; /
        ;
start1: call    showfn          ; show the save filename
        call    getdir          ; show directory enterys
        call    dopath          ; show current path
        call    dompab          ; show mpad status
        call    menus           ; draw menus
        mov     vpagen,1        ; set up for swaps
        mov     al,0            ; show page 0
        call    page            ; /       
        ;
start2: call    startt          ; start system timer
        call    initpd          ; initialize pointing device
        test    midiok,-1       ; was MIDI on?
        jz      start3          ; no, branch
        call    startm          ; yes, turn it on
        ;
start3: mov     curonf,1        ; no old cursor
        call    curon           ; activate cursor
        mov     pdf,80h         ; /
        call    fixhlt          ; fix halt status
;==============================================================
; registers that must be preserved: DS, SI
;==============================================================
; main work loop
        public work
work:
        if      debug           ; if true compile this stuff
        mov     al,really       ; if really, really do it
        or      al,al           ;  /
        jz      really1         ; /
        ;
        mov     bx,varnow       ; ...display the variable list
        sub     bx,8            ; back up a little
;--------------------------------------------------------------
; use this stuff to show MIDI data stream
comment |
;
        mov     bx, offset dgroup:mobuf;; get next byte
        add     bx,mobiix       ;; get midi in buffer index
        sub     bx,36           ; back up a little
        mov     ax,mobiix
        mov     show2,ax
        sub     ax,moboix
        mov     show3,ax
comment ends |
;--------------------------------------------------------------
; use this stuff to show mouse location & screen address
;
        mov     ax,curadr       ; cursor screen address
        mov     show0,ax        ; show it
        mov     al,pdx          ; cursor x
        mov     ah,pdy          ; cursor y
        mov     show1,ax        ; show it
        mov     show2,sp
;--------------------------------------------------------------
        call    showw           ;       /
        call    show            ;     /
really1:                        ;   /
        endif                   ; /
;==============================================================
; display time if on page 0
;
        mov     es,vpage                ; set up for video page
        cmp     vpagen,0                ; on page 0?
        jnz     work0                   ; no, branch
        mov     ah,2ch                  ; dos get time function
        int     21h                     ; call dos
        ;
        test    lodflg,-1               ; did a load happen
        jnz     workt                   ; yes, set new time
        ;
        cmp     cx,savtime              ; has time changed?
        jz      worktz                  ; no, branch
        ;
workt:  mov     colr,cyan               ; set color to cyan
        test    lodflg,-1               ; did a load happen
        jnz     workt2                  ; yes, don't check hrs
        cmp     ch,byte ptr savtime+1   ; hrs changed?
        jz      workt1                  ; no, branch
        ;
workt2: mov     al,ch                   ; setup for ascii
        mov     bx,clkadr               ; address of decimal readout
        call    todec                   ; show it in decimal
        mov     bx,clkadr               ; zip ms zero
        mov     byte ptr es:[bx],0b3h   ; /
        ;
workt1: mov     al,cl                   ; setup for ascii
        mov     bx,clkadr+6             ; address of decimal readout
        call    todec                   ; show it in decimal
        mov     bx,clkadr+6             ; zip ms zero
        mov     byte ptr es:[bx],':'    ; /
        ;
worktx: mov     savtime,cx              ; save time
        mov     colr,blue               ; fix color

worktz: dec     timecnt                 ; seconds changed?
        jnz     work0                   ; no, exit
;        mov     timecnt,64              ; yes, set new count  
        mov     bx,clkadr+7             ; flip colon color
        xor     byte ptr es:[bx],green  ; /
;--------------------------------------------------------------
; test to see if a request to change pages has been asserted
; 
work0:  cmp     pdf,82H         ; change page if pdf=2
        jnz     work0a          ; else, go on
        and     pdf,07fh        ; clear pen-down flag
        call    curoff          ; no cursor while changing pages
        mov     al,vpagep       ; get previous page number
        call    page            ; swap with current
        mov     curonf,1        ; don't restore screen data
        call    curon           ; do turn on the cursor
work0x: jmp     workx           ; back to the work loop
;==============================================================
; test to see if a command request has been asserted
;
work0a: cmp     pdf,81h         ; do command if pdf = 1
        jnz     work02          ; else check for user input
        and     pdf,07fh        ; clear pen-down flag
        cmp     pdx,2           ; in vertical menu area?
        jbe     workm0          ; yes, go do it     
        ;
        cmp     vpagen,0        ; on page 0?
        jnz     work01          ; no, branch
        cmp     pdy,10h         ; horiz menu?
        jz      workh           ; yes, go do it
        cmp     pdy,15h         ; below file area
        ja      work0x          ; yes, not interested
        cmp     pdy,11h         ; in file area?
        ja      workf           ; yes, go process
work01: jmp     work00          ; no, go process screen commands
workf:  jmp     workf0          ; branch to file area processing
workh:  jmp     workh0          ; branch to horiz menu processing
;==============================================================
; no putton push, if user input was requested (cmdflg =7 ), and
; if x,y position has changed, process user input
;
work02: mov     ax,11           ; check for mouse movement
        int     33H             ; /
        cmp     mickx,cx        ; has x changed?
        jnz     work02a         ; yes, go do it
        mov     ah,pdy          ; has y changed
        cmp     lasty,ah        ; /
        jz      work02x         ; no, then back to work loop

work02a:mov     mickx,cx        ; save x,y mickeys
        mov     al,pdx          ; save last pdx,pdy
        mov     lastx,al        ; yes, save pdx,pdy
        mov     ah,pdy          ;  /
        mov     lasty,ah        ; /
        cmp     cmdflg,7        ; blue input?
        jnz     work02b         ; no, branch
        jmp     work72          ; yes, process blue user input
work02b:cmp     cmdflg,10       ; magenta input?
        jnz     work02c         ; no, branch
        jmp     work92          ; yes, process magenta special input
work02c:
work02x:jmp     workx           ; no,  back to the work loop

;==============================================================
; Process Menu command.
;
workm0: cmp     pdy,7           ; page change command
        ja      workm1          ; no, go fish
        call    curoff          ; yes, set page
        mov     al,pdy          ;   /
        call    page            ; /
        mov     curonf,1        ; don't restore screen data
        call    curon           ; cursor back on
        jmp     workx           ; back to the work loop
;==============================================================
; menu commands other than page change
; 
workm1: cmp     pdy,8           ; ESC?
        jnz     workm4          ; no, branch
        jmp     workm1a         ; yes, go do it
workm4: cmp     pdy,10          ; SET?
        jnz     workm5          ; no, branch
        jmp     workm4a         ; yes, go do it
workm5:
        ;
workm2: cmp     cmdflg,0        ; something pending?
        jnz     workmz          ; yes, split
        ;
        cmp     pdy,9           ; delete?
        jnz     workm3          ; no, branch
        jmp     workm2a         ; yes, branch to delete
workm3: cmp     pdy,11          ; HLT?
        jnz     workm7          ; no, branch
        jmp     workm3a         ; yes, go do it
workm7: cmp     pdy,12          ; OFF?
        jnz     workm8          ; no, branch
        jmp     workm7a         ; yes, go do it
workm8: cmp     pdy,17          ; mute/solo command
        jb      workmz          ; no, exit
        jmp     workm8a         ; yes, go do it
        ;
workmz: jmp     workx           ; none of the above, exit

;==============================================================
; Delete command given, turn on highlite, set cmdflg to 4
;
workm2a:mov     bx,5a0h         ; address of DEL
        call    turnon          ; turn on
        mov     cmdflg,4        ; set command flag = 4
        mov     word ptr doesc,offset workm2d; set up for ESC
        jmp     workx           ; exit
;--------------------------------------------------------------
; escape from delete
;
workm2d:mov     bx,5a0h         ; turn off hilight
        jmp     turnoff
;==============================================================
; process HLT command (on/off)
;
workm3a:mov     bx,6E0H         ; text offset
        test    mprstf,2        ; stopped already?
        jz      workm3b         ; no, branch
        call    turnoff         ; yes, turn off highlight
        mov     al,0fah         ; send MIDI START command
        call    allmidi         ; send to all midi ports
        mov     mmtick,1        ; reset to 1st note in measure
        and     mprstf,0FDH     ; clear halt flag
        jmp     workx           ; exit
workm3b:call    turnon          ; turn on highlight
        or      mprstf,2        ; set master halt the flag
        mov     al,0fch         ; send MIDI STOP command
        call    allmidi         ; /
        jmp     workx           ; exit
;==============================================================
; SET  command given, save current system to temp file
;
workm4a:
        test    _tmpfn,-1       ; want to do it?
        jz      workm4e         ; no, branch
        ;
        cmp     cmdflg,0        ; was it clear?
        jz      workm4d         ; yes, branch
        jmp     workx           ; no, ignore
        ;
workm4d:mov     bx,160*10       ; address of menu text
        call    turnon          ; turn on highlight
        call    curoff          ; zip cursor
        call    allclr          ; clear all midi channels
        ;
        call    savmod          ; save modules
        ;
        mov     pdf,80h         ; reset mouse flag
        call    curon           ; cursor back on
        mov     bx,160*10       ; address of menu text
        call    turnoff         ; turn off highlight
        mov     clrchf,1        ; setup to clear chanl
workm4e:jmp     workx           ; exit
;==============================================================
; process OFF command (all notes off)
;
workm7a:
        call    alloff          ; process all notes off
        jmp     workx           ; exit
;==============================================================
; ESC command given.
; Turn cursor off, execute DOESC, then zip DOSEC.
; If cursor is a module image, turn it off.
; Clear cmdflg. 
;
        public  _cancel,cancel
_cancel:
workm1a:call    curoff          ; cursor off
cancel: mov     ax,doesc        ; get the esc exe addr
        call    ax              ; go do it
        mov     doesc,offset noop ; put it to sleep
        call    curon           ; cursor back on
        test    curflg,1        ; dragging a module around?
        jz      workm1d         ; no, branch
        call    setcur          ; yes, set cursor
workm1d:mov     cmdflg,0        ; clear command flag
        jmp     workx           ; exit
;--------------------------------------------------------------
; mute/solo commands
;
workm8a:test    mutef,1         ; action mute or solo?
        jnz     workm8e         ; branch if mute
        ;
        mov     dx,-1           ; set up solo mask
        mov     cl,pdy          ; point to the screen location
        sub     cl,17           ; cl = 0-7
        add     cl,cl           ; *2 for 0-14
        cmp     pdx,2           ; do odd?
        jz      workm8b         ; yes, branch
        mov     ax,1            ; set flag bit
        shl     ax,cl           ; ax = bit flag for mute
        xor     dx,ax           ; set the bit
        cmp     pdx,0           ; was this just even?
        jz      workm8c         ; yes, branch
workm8b:inc     cl              ; +1 for 1-15
        mov     ax,1            ; set flag bit
        shl     ax,cl           ; ax = bit flag for mute
        xor     dx,ax           ; set the bit
        ;
workm8c:cmp     dx,mute         ; same as last time?
        jnz     workm8d         ; no, branch
        mov     dx,0            ; yes, clear solo flags
workm8d:mov     mute,dx         ; set new solo
        jmp     workx           ; back to the work loop
;--------------------------------------------------------------
workm8e:mov     cl,pdy          ; point to the screen location
        sub     cl,17           ; cl = 0-7
        add     cl,cl           ; *2 for 0-14
        cmp     pdx,2           ; do odd?
        jz      workm8f         ; yes, branch
        mov     ax,1            ; set flag bit
        shl     ax,cl           ; ax = bit flag for mute
        xor     mute,ax         ; flip the bit
        cmp     pdx,0           ; was this just even?
        jz      workm8g         ; yes, branch
workm8f:inc     cl              ; +1 for 1-15
        mov     ax,1            ; set flag bit
        shl     ax,cl           ; ax = bit flag for mute
        xor     mute,ax         ; flip the bit
workm8g:jmp     workx           ; back to work loop
;==============================================================
; Process horiz page 0 menu
;
workh0: cmp     pdx,8           ; QUIT @ workh0a
        jnb     workh01         ;  /
        jmp     workh0a         ; /
workh01:cmp     pdx,0DH         ; EXIT @ workh1a
        jnb     workh02         ;  /
        test    room,-1         ; room to save?
        jz      workhx          ; no, ignore the command
        jmp     workh1a         ; /
workh02:cmp     pdx,12H         ; MPAD @ workh2a
        jnb     workh03         ;  /
        jmp     workh2a         ; /
workh03:cmp     pdx,17H         ; UNDO @ workh3a
        jnb     workh05         ;  /
        jmp     workh3a         ; /
workh05:cmp     pdx,1CH         ; REDO @ workh5a
        jnb     workh04         ; /
        jmp     workh5a         ; else go do it
workh04:cmp     pdx,21H         ; SAVE @ workh4a
        jnb     workh06         ;  /
        test    room,-1         ; room to save?
        jz      workhx          ; no, ignore the command
        jmp     workh4a         ; else go do it
workh06:cmp     pdx,2bh         ; NAME @ workh6a
        jnb     workh07         ;  /
        jmp     workh6a         ; /
workh07:jmp     workh7a         ; PATH @ workh7a
workhx: jmp     workx           ; back to the work loop
;--------------------------------------------------------------
; Turn on horiz menu command highlight.
; call with cursor on, bx = menu text offset
;
        public  horzon
horzon: push    bx              ; save text addr
        call    curoff          ; zip cursor
        pop     bx              ; get text addr
        add     bx,16*160       ; offset for line
        mov     dx,0b800h       ; do page 0 only
        mov     es,dx           ;
        or      byte ptr es:1[bx],8 ; make bright
        or      byte ptr es:3[bx],8 ;   /
        or      byte ptr es:5[bx],8 ;  /
        or      byte ptr es:7[bx],8 ; /
        mov     curonf,1        ; don't restore 
        jmp     curon           ; cursor normal
;--------------------------------------------------------------
; Turn off menu command highlight.
; call with cursor on, bx = menu text offset
;
        public  horzoff
horzoff:push    bx              ; save text addr
        call    curoff          ; zip cursor
        pop     bx              ; get text addr
        add     bx,16*160       ; offset for line
        mov     dx,0b800h       ; do page 0 only
        mov     es,dx           ;
        and     byte ptr es:1[bx],0f7h ; make dark  
        and     byte ptr es:3[bx],0f7h ;   /
        and     byte ptr es:5[bx],0f7h ;  /
        and     byte ptr es:7[bx],0f7h ; /
        mov     curonf,1        ; don't restore 
        jmp     curon           ; keep it right
;--------------------------------------------------------------
; show mapb status
;
dompab: mov     bx,1cH+(16*160) ; offset for line
        mov     dx,0b800h       ; do page 0 only
        mov     es,dx           ; /
        mov     al,_mpab        ; get it        
        mov     ah,1            ; set bit test flag
        mov     cl,4            ; 4 bits to do
dompab0:test    al,ah           ; look at the bit
        jz      dompab1         ; branch if off
        mov     byte ptr es:1[bx],cyan; else make bright
        jmp     short dompab2   ; branch
dompab1:mov     byte ptr es:1[bx],grey; make dark
dompab2:inc     bl              ; bump pointers
        inc     bl              ;  /
        shl     ah,1            ; /
        loop    dompab0         ; loop
        ret
;==============================================================
; QUIT command given, turn on highlite, set cmdflg to 6
;
workh0a:mov     bx,8            ; address of QUIT
        cmp     cmdflg,6        ; already set?
        jnz     workh0b         ; no, branch
        mov     dx,ds           ; yes, fix es = ds
        mov     es,dx           ; /
        test    _mpab,80H       ; has there been a save?
        jz      workh0e         ; no, branch
        call    delmod          ; delete temp file
workh0e:jmp     split           ; exit
workh0b:cmp     cmdflg,0        ; was it clear?
        jz      workh0d         ; yes, branch
        jmp     workx           ; no, ignore
workh0d:call    horzon          ; was clear, so turn on
        call    tmphlt          ; set temp hlt
        mov     cmdflg,6        ; set command flag = 6
        mov     doesc,offset workh0c ; set up ESC
        jmp     workx           ; exit
;--------------------------------------------------------------
; escape from QUIT
; also define "noop" as a dummy return
;
workh0c:mov     bx,8            ; turn off highlight
        call    horzoff         ; /
        call    clrhlt          ; clear hlt 
noop:   ret                     ; "noop" is dummy return
;==============================================================
; EXIT command given, turn on highlite, set cmdflg to 18
;
workh1a:mov     bx,12h          ; address of EXIT
        cmp     cmdflg,16       ; already set?
        jnz     workh1b         ; no, branch
        mov     cmdflg,0        ; clear the command
        ;
        call    horzoff         ; yes, turn off highlight
        mov     bx,3ah          ; zip save highlight
        call    horzoff         ; /
        call    curoff          ; zip cursor
        ;
        call    delmod          ; delete temp file
        ;
        mov     dx,ds           ; fix es = ds
        mov     es,dx           ; /
        ;
        test    _bakfn,-1       ; doing backups?
        jz      workh1e         ; no, branch
        ;
        mov     dx,offset dgroup:_savfn; file already exists?
        mov     cx,0            ; /
        mov     ah,4eh          ; dos search for first
        int     21h             ; /
        jc      workh1e         ; branch if not already existing
        ;
        mov     dx,offset dgroup:_bakfn; delete old bakfn
        mov     ah,41h          ; dos delete function call
        int     21h             ; /
        ;
        mov     dx,offset dgroup:_savfn; rename savfn to bakfn
        mov     di,offset dgroup:_bakfn
        mov     ah,56h          ; dos rename function call
        int     21h             ; /
        ;
workh1e:mov     dx,offset dgroup:_savfn; point to file name
        call    savmods         ; save modules
        test    errflg,-1       ; any errors?
        jz      workh1f         ; no, branch
        mov     dx,offset dgroup:_errwx; yes, setup message
        call    errmsg          ; do msg, get response
        cmp     al,'Q'          ; want to ignore?
        jz      workh1f         ; /
        cmp     al,'R'          ; Retry
        jz      workh1e         ; /
        ;                       ; else Escape
        mov     pdf,80h         ; reset mouse flag
        call    curon           ; cursor back on
        call    workh1c         ; fix menu & HLT status
        call    getdir          ; show directory
        jmp     workx           ; exit
        ;
workh1f:jmp     split           ; exit
        ;
workh1b:cmp     cmdflg,0        ; was it clear?
        jz      workh1d         ; yes, branch
        jmp     workx           ; no, ignore
        ;
workh1d:call    horzon          ; was clear, so turn on
        mov     bx,3ah          ; set save highlight
        call    horzon          ; /
        call    tmphlt          ; set temp hlt
        mov     cmdflg,16       ; set command flag = 18
        mov     doesc,offset workh1c ; set up ESC
        jmp     workx           ; exit
;--------------------------------------------------------------
; escape from EXIT
;
workh1c:mov     bx,12h          ; turn off highlight
        call    horzoff         ; /
        mov     bx,3ah          ; zip save highlight
        call    horzoff         ; /
        call    clrhlt          ; clear temp hlt
        ret
;==============================================================
; set MPAB bit & display status
;
workh2a:mov     ah,1            ; set bit flag
        mov     dh,pdx          ; get cursor x-loc
        mov     dl,0EH          ; first match position
        mov     cx,4            ; 4 to do
workh2b:cmp     dl,dh           ; match?
        jz      workh2c         ; yes, branch out
        shl     ah,1            ; bump bit flag
        inc     dl              ; bump x-loc
        loop    workh2b         ; do them all
workh2c:xor     _mpab,ah        ; flip the mpab bit
        call    curoff          ; zip cursor
        call    dompab          ; show it
        mov     curonf,1        ; don't restore 
        call    curon           ; keep it right
        jmp     workx           ; exit
;==============================================================
; UNDO command given, turn on highlite, set cmdflg to 16
;
workh3a:
        test    _tmpfn,-1       ; want to do it?
        jz      workh3e         ; no, branch
        ;
        mov     bx,26h          ; address of UNDO
        cmp     cmdflg,17       ; already set?
        jnz     workh3b         ; no, branch
        mov     cmdflg,0        ; clear the command
        ;
        call    curoff          ; zip cursor
        xor     _tmpfn+4,1      ; switch file name
        call    savmod          ; save modules
        xor     _tmpfn+4,1      ; switch file name
        call    lodmod          ; load modules
        ;
        call    delmod          ; delete just loaded file
        xor     _tmpfn+4,1      ; switch file name
        ;
        call    showfn          ; show the save filename
        call    getdir          ; show directory enterys
        call    dopath          ; show current path
        call    dompab          ; show mpad status
        call    menus           ; draw menus
        ;
        mov     pdf,80h         ; reset mouse flag
        mov     curonf,1        ; don't restore
        call    curon           ; cursor back on
        mov     bx,26h          ; turn off highlight
        call    horzoff         ; /
        mov     bx,160*10       ; address of menu text
        call    turnoff         ; turn off highlight
        call    showfn          ; show exit file name
        call    fixhlt          ; clear temp HLT
        mov     lodflg,2        ; flag that a load happened
workh3e:jmp     workx           ; exit
        ;
workh3b:cmp     cmdflg,0        ; was it clear?
        jz      workh3d         ; yes, branch
        jmp     workx           ; no, ignore
        ;
workh3d:mov     bx,26h          ; point menu text
        call    horzon          ; turn on
        call    tmphlt          ; set temp HLT
        mov     cmdflg,17       ; set command flag = 19
        mov     doesc,offset workh3c ; set up ESC
        jmp     workx           ; exit
;--------------------------------------------------------------
; escape from UNDO
;
workh3c:mov     bx,26h          ; turn off highlight
        call    horzoff         ; /
        call    clrhlt          ; clear temp hlt
        ret
;==============================================================
; SAVE command given, turn on highlite, set cmdflg to 19
;
workh4a:cmp     cmdflg,19       ; already set?
        jnz     workh4b         ; no, branch
        mov     cmdflg,0        ; clear the command
        ;
        mov     bx,3ah          ; point to text
        call    horzoff         ; turn off highlight
        call    curoff          ; zip cursor
        ;
        mov     dx,ds           ; fix es = ds
        mov     es,dx           ; /
        ;
        test    _bakfn,-1       ; doing backups?
        jz      workh4e         ; no, branch
        ;
        mov     dx,offset dgroup:_savfn; file already exists?
        mov     cx,0            ; /
        mov     ah,4eh          ; dos search for first
        int     21h             ; /
        jc      workh4e         ; branch if not already existing
        ;
        mov     dx,offset dgroup:_bakfn; delete old bakfn
        mov     ah,41h          ; dos delete function call
        int     21h             ; /
        ;
        mov     dx,offset dgroup:_savfn; rename savfn to bakfn
        mov     di,offset dgroup:_bakfn
        mov     ah,56h          ; dos rename function call
        int     21h             ; /
        ;
workh4e:mov     dx,offset dgroup:_savfn; point to file name
        call    savmods         ; save modules
        test    errflg,-1       ; any errors?
        jz      workh4f         ; no, branch
        mov     dx,offset dgroup:_errwr; yes, setup message
        call    errmsg          ; do msg, get response
        cmp     al,'I'          ; want to ignore?
        jz      workh4f         ; /
        cmp     al,'R'          ; Retry
        jz      workh4e         ; /
        jmp     split           ; must be split
        ;
workh4f:
        mov     pdf,80h         ; reset mouse flag
        call    curon           ; cursor back on
        call    workh4c         ; fix menu & HLT status
        call    getdir          ; show directory
        jmp     workx           ; exit
        ;
workh4b:cmp     cmdflg,0        ; was it clear?
        jz      workh4d         ; yes, branch
        jmp     workx           ; no, ignore
        ;
workh4d:mov     bx,3ah          ; point menu text
        call    horzon          ; turn on
        call    tmphlt          ; set temp HLT
        mov     cmdflg,19       ; set command flag = 19
        mov     doesc,offset workh4c ; set up ESC
        jmp     workx           ; exit
;--------------------------------------------------------------
; escape from SAVE
;
workh4c:mov     bx,3ah          ; turn off highlight
        call    horzoff         ; /
        call    clrhlt          ; fix hlt status
        ret
;==============================================================
; REDO command given, turn on highlite, set cmdflg to 18
;
workh5a:
        test    _tmpfn,-1       ; want to do it?
        jz      workh5e         ; no, branch
        ;
        mov     bx,30h          ; address of UNDO
        cmp     cmdflg,18       ; already set?
        jnz     workh5b         ; no, branch
        mov     cmdflg,0        ; clear the command
        ;
        call    curoff          ; zip cursor
        call    lodmod          ; load modules
        ;
        call    showfn          ; show the save filename
        call    getdir          ; show directory enterys
        call    dopath          ; show current path
        call    dompab          ; show mpad status
        call    menus           ; draw menus
        ;
        mov     pdf,80h         ; reset mouse flag
        mov     curonf,1        ; don't restore
        call    curon           ; cursor back on
        mov     bx,26h          ; turn off highlight
        call    horzoff         ; /
        mov     bx,160*10       ; address of menu text
        call    turnoff         ; turn off highlight
        call    showfn          ; show exit file name
        call    fixhlt          ; clear temp HLT
        mov     lodflg,2        ; flag that a load happened
workh5e:jmp     workx           ; exit
        ;
workh5b:cmp     cmdflg,0        ; was it clear?
        jz      workh5d         ; yes, branch
        jmp     workx           ; no, ignore
        ;
workh5d:mov     bx,30h          ; point menu text
        call    horzon          ; turn on
        call    tmphlt          ; set temp HLT
        mov     cmdflg,18       ; set command flag = 19
        mov     doesc,offset workh5c ; set up ESC
        jmp     workx           ; exit
;--------------------------------------------------------------
; escape from REDO
;
workh5c:mov     bx,30h          ; turn off highlight
        call    horzoff         ; /
        call    clrhlt          ; clear temp hlt
        ret
;--------------------------------------------------------------
; NAME command, put new name in _savfn
;
workh6a:call    curoff                  ; zip cursor
        ;
        mov     ah,2                    ; bios set cursor position
        mov     bh,0                    ; page 0
        mov     dx,1023H                ; x,y of cursor
        int     10H                     ; do bios int
        ;
        mov     _savfn,'.'              ; clear the name area
        call    showfn                  ; /
        mov     _inbuf,9                ; 8 chars max
        call    getkey                  ; get them
        ;
        mov     cx,8                    ; put them in savfn
        mov     bx,offset dgroup:_inbuf+2;  /
        mov     di,offset dgroup:_savfn ; /
workh6b:mov     al,[bx]                 ; get the char
        cmp     al,21h                  ;  /
        jb      workh6d                 ; /
        mov     [di],al                 ; put char in savfn buffer
        inc     di                      ; bump fn pointer
        inc     bx                      ; bump cmd line pointer
        loop    workh6b                 ; loop to max of input chars
        ;
workh6d:mov     byte ptr   [di],'.'     ; set up save extension
        mov     byte ptr  1[di],'M'     ;    /
        mov     byte ptr  2[di],'B'     ;   /
        mov     byte ptr  3[di],' '     ;  /
        mov     byte ptr  4[di],0       ; /
        call    showfn                  ; show it
        mov     curadr,0a44h            ; set cursor to 0th char
        mov     curonf,1                ; don't restore
        call    curon                   ; but turn it on
        mov     pdf,80h                 ; /
        mov     clrchf,1                ; setup to clear chanl
        jmp     workx                   ; exit
;--------------------------------------------------------------
; PATH command, set new directory path
;
workh7a:call    curoff                  ; zip cursor
        ;
        mov     ax,0b800h               ; set up video seg
        mov     es,ax                   ; /
        mov     bx,58H+(16*160)         ; offset for line
        mov     ax,whi                  ; set color
        mov     cx,35                   ; words in line
workh7b:mov     es:[bx],ax              ; set the word
        inc     bx                      ; bump
        inc     bx                      ; /
        loop    workh7b                 ; do the line
        ;
        mov     ah,2                    ; bios set cursor position
        mov     bh,0                    ; page 0
        mov     dx,102CH                ; x,y of cursor
        int     10H                     ; do bios int
        ;
        mov     _inbuf,36               ; 36 chars max
        call    getkey                  ; get them
        mov     al,_inbuf+1             ; get number of chars
        mov     ah,0                    ;  /
        mov     bx,offset dgroup:_inbuf+2;/
        mov     dx,bx                   ; save for path
        add     bx,ax                   ; point to end of string
        mov     byte ptr [bx],0         ; null terminate
        ;
        mov     ah,19h                  ; get current disk drive
        int     21h                     ; dos call
        mov     _inbuf,al               ; put it away
        ;
        cmp     byte ptr _inbuf+2,'\'   ; directory or drive?
        jz      workh7c                 ; branch if directory
        ;
        mov     al,_inbuf+2             ; get the new drive
        call    touc                    ; make uppercase
        sub     al,'A'                  ; make A=0, B=1, etc.
        mov     dl,al                   ; set up for dos call
        mov     ah,0eh                  ; set default drive
        int     21h                     ; dos call
        ;
        cmp     byte ptr _inbuf+4,'\'   ; drive change only
        jnz     workh7d                 ; yes, don't change path
        ;
workh7c:mov     ah,3bh                  ; set new path
        mov     dx,offset dgroup:_inbuf+2;/
        int     21h                     ; dos call
        jnc     workh7d                 ; branch if ok
        ;
        mov     dl,_inbuf               ; else get old drive
        mov     ah,0eh                  ; set default drive
        int     21h                     ; dos call
        ;
workh7d:call    dopath                  ; show it
        call    getdir                  ; show new directory
        ;
        mov     curadr,0a56h            ; set cursor to 0th char
        mov     curonf,1                ; don't restore
        call    curon                   ; but turn it on
        mov     pdf,80h                 ; /
        jmp     workx                   ; exit
;==============================================================
; Process file area loads, set cmdflg = 20
;
workf0: call    curoff                  ; zip cursor
        mov     bx,0b800H               ; setup video seg
        mov     es,bx                   ; /
        mov     bx,curadr               ; get cursor address
        mov     al,es:1[bx]             ; get attribute byte
        and     al,lo                   ; strip highlight
        cmp     al,yellow               ; got anything? 
        jz      workf0a                 ; yes, branch
        jmp     workfq                  ; no, cancel the command
        ;
workf0a:cmp     byte ptr es:[bx],' '    ; is it a letter
        ja      workf1                  ; yes, go on
        jmp     workfq                  ; no, cancel
        ;
workf1: dec     bx                      ; no, back up
        dec     bx                      ; /
        cmp     byte ptr es:[bx],' '    ; look for 1st non-letter
        ja      workf1                  ; /
        inc     bx                      ; point to start
        inc     bx                      ; /
        ;
        cmp     cmdflg,20               ; ready to do it
        jz      workf1a                 ; yes, branch
        cmp     cmdflg,4                ; DEL
        jz      workf1b                 ; yes, branch
        jmp     workf8                  ; no, exit
        ;
workf1a:test    byte ptr es:1[bx],hi    ; hi bit set
        jnz     workf1b                 ; yes, go on
        jmp     workfq                  ; no, cancel
        ;
workf1b:mov     di,offset dgroup:_lodfn ; point to file text area
        mov     cx,8                    ; 8 maximum to do
workf3: mov     al,es:[bx]              ; get first char
        cmp     al,' '                  ; ignore spaces
        jna     workf2                  ; /
        mov     [di],al                 ; put char in save file name buffer
        inc     bx                      ; bump screen pointer
        inc     bx                      ; /
        inc     di                      ; bump text pointer
        loop    workf3                  ; loop to max
        ;
workf2: mov     byte ptr [di],'.'       ; set up extension
        mov     byte ptr 1[di],'M'      ;    /
        mov     byte ptr 2[di],'B'      ;   /
        mov     byte ptr 3[di],' '      ;  /
        mov     byte ptr 4[di],0        ; /
        ;
        cmp     cmdflg,20               ; want to load?
        jz      workf2a                 ; yes, go do it
        mov     ah,41H                  ; else DEL file
        mov     dx,offset dgroup:_lodfn ; point to file name
        int     21H                     ; zap it
        mov     cmdflg,0                ; clear the cmd
        call    getdir                  ; show directory enterys
        mov     pdf,80h                 ; reset mouse flag
        mov     curonf,1                ; don't restore
        call    curon                   ; but turn it on
        mov     bx,5a0h                 ; turn off DEL hilight
        call    turnoff                 ; /
        jmp     workx                   ; split
        ;
workf2a:
        mov     ah,3dh                  ; dos open file command
        mov     al,0                    ; read only
        mov     dx,offset dgroup:_lodfn ; point to file name
        int     21H                     ; open the file
        jc      workf6                  ; exit if error
        call    lodmod0                 ; load modules
        ;
workf6: call    showfn                  ; show the save filename
        call    getdir                  ; show directory enterys
        call    dopath                  ; show current path
        call    dompab                  ; show mpad status
        call    menus                   ; draw menus
        ;
workfx: mov     cmdflg,0                ; reset
        mov     pdf,80h                 ; fix mouse flag
workfz: mov     curonf,1                ; don't restore
        call    curon                   ; but turn it on
        call    fixhlt                  ; fix hlt status
        mov     lodflg,2                ; flag that a load happened
        jmp     workx                   ; exit
        ;
workfq: mov     pdf,80h                 ; /
        jmp     cancel                  ; so forget it
;--------------------------------------------------------------
; cmdflg was not alreay 20, setup new one
;
workf8: cmp     cmdflg,0                ; was it clear?
        jz      workf9                  ; yes, branch
        jmp     cancel                  ; no, cancel
        ;
workf9: mov     dirptr,bx               ; text location
        call    dirnon                  ; highlight
        call    tmphlt                  ; set temp HLT
        mov     cmdflg,20               ; set command flag = 20
        mov     doesc,offset workf10    ; set up ESC
        mov     curonf,1                ; don't restore
        call    curon                   ; but turn it on
        jmp     workx                   ; exit
;--------------------------------------------------------------
; escape from DIR load
;
workf10:call    clrhlt                  ; fix hlt status
        call    dirnoff                 ; lowlight
        ret
;--------------------------------------------------------------
; highlight a directory file name
; call with cursor OFF
;
dirnon: mov     cx,8                    ; 8 chars to do
        mov     bx,0b800h               ; do page 0 only
        mov     es,bx                   ;
        mov     bx,dirptr               ; get last picked name
dirnon1:
        or      byte ptr es:1[bx],hi    ; make bright
        inc     bx                      ; bump pointer
        inc     bx                      ; /
        loop    dirnon1                 ; do all 8
        ret
;--------------------------------------------------------------
; loghlight a directory file name
; call with cursor ON
;
dirnoff:call    curoff                   ; cursor on
        mov     cx,8                    ; 8 chars to do
        mov     bx,0b800h               ; do page 0 only
        mov     es,bx                   ;
        mov     bx,dirptr               ; get last picked name
dirnoff1:
        and     byte ptr es:1[bx],lo    ; make dark  
        inc     bx                      ; bump pointer
        inc     bx                      ; /
        loop    dirnoff1                ; do all 8
        mov     curonf,1                ; don't restore 
        jmp     curon                   ; keep it right
;==============================================================
; Process Screen command.
;
work0bx:jmp     workx           ; split
        ;
work00:
        call    curoff          ; cursor off while reading screen
        call    cmdchk          ; get new cmdloc, ptr, tag, cnt, & col
        cmp     vpagen,0        ; on page 0?
        jz      work0b          ; yes, branch
        cmp     cmdflg,3        ; reincarnate?
        jz      work0b          ; yes, branch
        call    varlst          ; else find the variable list
        or      di,di           ; is it good
        jz      work0b          ; no, branch
        mov     varnow,di       ; save it
work0b: call    curon           ; cursor back on
        cmp     cmdflg,3        ; move, copy, or reincarnate?
        ja      workp0          ; no, process other stuff
        jmp     work20a         ; yes, branch
;--------------------------------------------------------------
; process pending commands > 3
; 4 = delete module
; 5 = priority swap
; 6 = bye
; 7 = user variable input
; 8 = flagged output to variable input
; 9 = special user input (magenta inputs )
; 
workp0: cmp     cmdflg,4        ; delete?
        jnz     workp1          ; /
        jmp     workpa          ; yes, go do the delete
workp1: cmp     cmdflg,5        ; priority?
        jnz     workp2          ; /
        jmp     work6           ; yes, go do the priority swap
workp2: cmp     cmdflg,6        ; trying to QUIT
        jnz     workp3          ; /
        jmp     _cancel         ; yes, kill it
workp3: cmp     cmdflg,7        ; user input value?
        jnz     workp4          ; /
        jmp     _cancel         ; yes, set it
workp4: cmp     cmdflg,8        ; flagged output value?
        jnz     workp5          ; /
        jmp     work8           ; yes, go set the value
workp5: cmp     cmdflg,9        ; special user input?
        jnz     workp6          ; /
        jmp     work9           ; yes, go process magenta stuff
workp6: cmp     cmdflg,10       ; special user input?
        jnz     workp7          ; /
        jmp     work9           ; yes, go process magenta stuff
workp7: cmp     cmdflg,16       ; EXIT?
        jnz     workp8          ;  /
        jmp     _cancel         ; yes, kill it
workp8: cmp     cmdflg,17       ; UNDO?
        jnz     workp9          ;  /
        jmp     _cancel         ; yes, kill it
workp9: cmp     cmdflg,18       ; REDO?
        jnz     workp10         ; /
        jmp     _cancel         ; yes, kill it
workp10:cmp     cmdflg,19       ; was SAVE set?
        jnz     workp11         ; /
        jmp     _cancel         ; yes, kill it
workp11:cmp     cmdflg,20       ; was directory load pending
        jnz     workp12         ; /
        jmp     _cancel         ; yes, kill it
workp12:
workpq: mov     cmdflg,0        ; no, clear the flag
        jmp     workx           ; back to the work loop

;--------------------------------------------------------------
; no command pending above 3, check if cursor is a module,
; if it is branch to work2a to do the pending create or move.
; Otherwise, check color under cursor.
; If white branch to work2e to set up a pending move/create.
; If color is not white branch to work1 for further processing.
;
work20a:test    curflg,1        ; already dragging something around?
        jz      work20c         ; yes, go do something with it
        jmp     work2a          ; /
work20c:cmp     cmdcol,7        ; is this a module pickup?
        jz      work2e          ; yes, go do it
        jmp     work1           ; no, go do something else
;==============================================================
; Module pickup requested: don't do anything except set the module
; to be the cursor (so it can be dragged around), and set cmdflg
; to indicate a pending module create or move.  If currently on
; page 0, a new module will be created, if on any other page, the
; existing module will be moved.  Nothing is done, however, until
; the next command request.  Modules with "*" for the module number
; are not allowed to be picked up. 
; Modules with "X" will be reincarnated.
;
work2e: cmp     vpagen,0        ; is this page 0?
        jnz     work2d          ; no, branch
        mov     bx,cmdloc       ; get the module number
        mov     es,vpage        ;   /
        cmp     byte ptr es:2[bx],'*'; out of gas?
        jnz     work2e1         ; no, go on
        jmp     workx           ; yes, exit
work2e1:cmp     byte ptr es:2[bx],'X'; a deleted module?
        jnz     work2e2         ; no, go on
        jmp     workr           ; yes, go reincarnate it.
work2e2:mov     bx,cmdptr       ; set up the cursor
        mov     ax,2[bx]        ; ... to be the module
        mov     modchar,ax      ; the module source text
        call    setmod          ; ... is now the cursor
        mov     cmdflg,1        ; set the command flag
        jmp     workx           ; back to the work loop
;==============================================================
; It's not on page 0, so setup a copy of the existing module
;
work2d: call    curoff          ; turn cursor off
        mov     ax,varnow       ; get variable table address
        mov     tmpsav,ax       ; save it
        mov     bx,cmdptr       ; set up the cursor
        mov     ax,2[bx]        ; ... to be the module
        mov     bx,ax           ; point to module source text
        mov     di,offset dgroup:$dummy; gonna put it in the dummy
        mov     cx,[bx]         ; get number of lines in module
        mov     [di],cx         ; store in dummy buffer
        add     di,4            ; bump index
        mov     bx,cmdloc       ; point to current screen text
        mov     es,vpage        ; get current screen seg
work2d1:mov     ax,es:-2[bx]    ; get left word
        mov     [di],ax         ; put in dummy
        or      byte ptr es:-1[bx],80h ; blink
        inc     di              ; bump index
        inc     di              ; /
        mov     ax,es:[bx]      ; get center word
        mov     [di],ax         ; put in dummy
        or      byte ptr es:1[bx],80h ; blink
        inc     di              ; bump index
        inc     di              ; /
        mov     ax,es:2[bx]     ; get right word 
        mov     [di],ax         ; put in dummy
        or      byte ptr es:3[bx],80h ; blink
        inc     di              ; bump index
        inc     di              ; /
        add     bx,160          ; next line
        loop    work2d1         ; loop til done
        mov     modchar,offset dgroup:$dummy ; set dummy as cursor source
        mov     curonf,1        ; don't replace blinking label
        call    curon           ; keep it even
        call    setmod          ; dummy copy is now the cursor
        mov     cmdflg,2        ; set the command flag
        mov     doesc, offset work2dx; setup for ESC
        jmp     workx           ; back to the work loop
;--------------------------------------------------------------
; escape from move
; fixes blinking module
;
work2dx:mov     di,tmpsav       ; find variable list
        mov     es,4[di]        ; get screen seg
        mov     bx,6[di]        ; get screen addr
        mov     di,[di]         ; get number of lines
        mov     di,2[di]        ;   /
        mov     cx,[di]         ; /
        jmp     unblink         ; zip blinking
;==============================================================
; Set up to drag around a gost module (module # = "X")
;
workr:  call    curoff          ; zip old cursor
        mov     bx,cmdptr       ; set up new cursor...
        mov     tmpsav,bx       ; (save MODSRC for later)
        mov     ax,2[bx]        ; ... to be the module
        mov     bx,ax           ; point to module source text
        mov     di,offset dgroup:$dummy; gonna put it in the dummy
        mov     cx,[bx]         ; get number of lines in module
        mov     [di],cx         ; store in dummy buffer
        add     di,4            ; bump index
        add     bx,4            ;
workr1: mov     ax,[bx]         ; get left word
        mov     [di],ax         ; put in dummy
        inc     di              ; bump index
        inc     di              ;     /
        inc     bx              ;   /
        inc     bx              ; /
        mov     ax,[bx]         ; get center word
        mov     [di],ax         ; put in dummy
        inc     di              ; bump index
        inc     di              ;     /
        inc     bx              ;   /
        inc     bx              ; /
        mov     ax,[bx]         ; get right word 
        cmp     ah,white        ; this a label?
        jnz     workr2          ; no, branch
        mov     al,'X'          ; yes, change number to 'X'
workr2: mov     [di],ax         ; put in dummy
        inc     di              ; bump index
        inc     di              ;     /
        inc     bx              ;   /
        inc     bx              ; /
        loop    workr1          ; loop til done
        mov     modchar,offset dgroup:$dummy ; set dummy as cursor source
        mov     curonf,1        ; don't replace blinking label
        call    curon           ; keep it even
        call    setmod          ; dummy copy is now the cursor
        mov     cmdflg,3        ; set the command flag for reincarnate
        jmp     workx           ; back to the work loop
;==============================================================
; case of not currently dragging something, color <> white
; possible commands (all not page 0):
;       grey:    priority swap
;       cyan:    flag output for value input from cmdflg = 7
;       blue:    value input from user
;       green:   value input from user
;       magenta: user input


work1: cmp     vpagen,0         ; in page 0
        jz      work1x          ; yes, go back to the work loop
        ;                       ; no, ( process other commands)
        cmp     cmdcol,grey     ; priority swap?
        jnz     work1b          ; no, branch
        jmp     work60          ; yes, go do the priority swap
work1b: cmp     cmdcol,blue     ; value input from user?
        jnz     work1bb         ; no, branch
        jmp     work70          ; yes, go do user input
work1bb:cmp     cmdcol,green    ; value input from user?
        jnz     work1c          ; no, branch
        jmp     work70          ; yes, go do user input
work1c: cmp     cmdcol,cyan     ; output value flagged?
        jnz     work1d          ; no, branch
        jmp     work80          ; yes, process output value flag
work1d: cmp     cmdcol,magenta  ; want special user input
        jnz     work1x          ; no, branch
        jmp     work90          ; yes set up for special input
work1x: jmp     workx           ; and back to the work loop
;==============================================================
; Priority selected, set cmdflg = 5
;
work60: mov     cmdflg,5        ; set the flag
        call    curoff          ; turn cursor off
        mov     ax,varnow       ; get variable table address
        mov     tmpsav,ax       ; save it
        mov     bx,cmdtag       ; highlight the command
        mov     es,vpage        ;          /
        or      byte ptr es:161[bx],7;   /
        or      byte ptr es:163[bx],7; /
        mov     curonf,1        ; don't restore
        call    curon           ; normal cursor
        mov     doesc,offset work61 ; set up for ESC
        jmp     workx           ; back to the work loop
;--------------------------------------------------------------
; escape from priority swap
;
work61: mov     di,tmpsav       ; turn off highlight
        mov     es,4[di]        ; get seg
        mov     bx,6[di]        ; get addr
        mov     byte ptr es:161[bx],grey; zip hilight
        mov     byte ptr es:163[bx],grey; /
        mov     curonf,1        ; don't restore cursor
        ret
;==============================================================
; Output flag selected, set cmdflg = 8
;
work80: mov     cmdflg,8        ; set the flag
        call    curoff          ; turn cursor off
        mov     ax,varnow       ; get variable table address
        mov     tmpsav,ax       ; save it
        mov     bx,cmdloc       ; highlight the command
        mov     locsav,bx       ; (save hilight addr)
        mov     es,vpage        ; /
        or      byte ptr es:1[bx],hi;   /
        or      byte ptr es:3[bx],hi; /
        mov     bx,cmdtag       ; get icon tag
        mov     al,es:[bx]      ;  /
        mov     ah,es:2[bx]     ; /
        mov     shosav,ax       ; save it
        mov     curonf,1        ; don't restore
        call    curon           ; normal cursor
        mov     doesc,offset work81 ; set up for ESC
        jmp     workx           ; back to the work loop
;--------------------------------------------------------------
; escape from flag output command
;
work81: mov     di,tmpsav       ; turn off highlight
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        and     byte ptr es:1[bx],lo; zip hilight
        and     byte ptr es:3[bx],lo; /
;--------------------------------------------------------------
; lowlight all inputs currently associated with output
; if shoflg = 1
;
        test    shoflg,1        ; wanna show inputs?
        jz      work81d         ; no, branch
        mov     shoflg,0        ; yes, zip flag
        mov     ax,shosav       ; get icon tag
        push    ds              ; save data seg
        mov     cx,0b800H       ; point to color screen
        mov     ds,cx           ; /
        mov     cx,4000H        ; 16K words to look at
        mov     bx,0            ; set up index
work81c:cmp     al,[bx]         ; got an icon match?
        jz      work81e         ; yes, go look
        ;
work81b:inc     bx              ; no, bump address
        inc     bx              ; /
        loop    work81c         ; loop
        pop     ds              ; restore data seg
        mov     pdf,80h         ; reset mouse flag        
work81d:mov     curonf,1        ; don't restore cursor
        ret                     ; exit
        ;
work81e:cmp     ah,2[bx]        ; got a module match
        jnz     work81b         ; no, go loop
        cmp     byte ptr 1[bx],green OR hi; is it a green label?
        jnz     work81b         ; no, go loop 
        and     byte ptr 1[bx],lo; zip hilight
        and     byte ptr 3[bx],lo; /
        jmp     short work81b   ; go to loop
;--------------------------------------------------------------
; process flagged output to become an input variable
;
work8:  call    curoff
        cmp     cmdcol,blue     ; was an input variable selected?
        jz      work8y          ; yes, do it
        cmp     cmdcol,green    ; was an input variable selected?
        jz      work8y          ; yes, go doit
        cmp     cmdcol,cyan OR hi; wanna show exitsting connections
        jnz     work8x          ; no, exit
;--------------------------------------------------------------
; highlight all inputs currently associated with output
;
        mov     shoflg,1        ; set the show flag
        call    curoff          ; turn cursor off
        mov     ax,shosav       ; get module icon
        push    ds              ; save data seg
        mov     cx,0b800H       ; point to color screen
        mov     ds,cx           ; /
        mov     cx,4000H        ; 16K words to look at
        mov     bx,0            ; set up index
work80c:cmp     al,[bx]         ; got an icon match?
        jz      work80e         ; yes, go look
        ;
work80b:inc     bx              ; no, bump address
        inc     bx              ; /
        loop    work80c         ; loop
        ;
        pop     ds              ; restore data seg
        mov     curonf,1        ; don't restore
        mov     pdf,80h         ; reset mouse flag
work8x: call    curon           ; normal cursor
        jmp     workx           ; exit
        ;
work80e:cmp     ah,2[bx]        ; got a module match
        jnz     work80b         ; no, go loop
        cmp     byte ptr 1[bx],green; is it a green label
        jnz     work80b         ; no, go loop 
        or      byte ptr 1[bx],hi;yes, set the highlight
        or      byte ptr 3[bx],hi; /
        jmp     short work80b   ; go to loop
;--------------------------------------------------------------
; connect flagged output to input
;
work8y: mov     cmdflg,0        ; yes, clear cmdflg
        call    work81          ; clear the highlight
        mov     bx,6[di]        ; get the screen addr of source module
        mov     es,4[di]        ; get screen seg of module
        mov     dl,es:[bx]      ; dl = tag character
        mov     dh,es:2[bx]     ; dh = module number tag
        ;
        mov     cx,di           ; calculate the output address
        add     cx,8            ; cx = address of output value
        ;
        mov     es,vpage        ; get current screen seg
        mov     bx,cmdloc       ; get current variable pointer
        mov     es:[bx],dl      ; set the label to input module
        mov     es:2[bx],dh     ; /
        mov     al,green        ; set the color to green
        mov     es:1[bx],al     ;   /
        mov     es:3[bx],al     ; /
        ;
        mov     ax,0            ; find out which value it is
work80a:sub     bx,160          ;       /
        add     ax,2            ;     /
        cmp     byte ptr es:1[bx],blue
        jz      work80a         ; /
        cmp     byte ptr es:1[bx],green
        jz      work80a         ; /
        mov     bx,ax           ; bx = word offset to variables
        mov     di,varnow       ; get current variable table
        mov     10[bx+di],cx    ; set address of new variable
        ;
        call    curon
        jmp     workx
;==============================================================
; User value input selected, set cmdflg = 7
;
work70: mov     cmdflg,7        ; set the flag
        call    curoff          ; turn cursor off
        mov     ax,varnow       ; get variable table address
        mov     tmpsav,ax       ; save it
        mov     bx,cmdloc       ; highlight the command
        mov     locsav,bx       ; (save hilight addr)
        mov     es,vpage        ;       /
        or      byte ptr es:1[bx],hi;  /
        or      byte ptr es:3[bx],hi; /
        mov     ax,0            ; find out which value it is
work70a:sub     bx,160          ;        /
        add     ax,2            ;       /
        cmp     byte ptr es:1[bx],blue;/
        jz      work70a         ;     /
        cmp     byte ptr es:1[bx],green
        jz      work70a         ;   /
        mov     holdv,ax        ; save the offset
        ;
        mov     bx,holdv        ; read current value
        mov     di,tmpsav       ; get value table for module
        mov     bx,10[bx+di]    ; bx = address of value
        mov     dl,[bx]         ; dl = binary value
        mov     dh,0            ; make into a word
        add     dx,dx           ; make into a word
        add     dx,offset dgroup:@zero; dx = address pointer into number table
        mov     bx,holdv        ; get offset to the value
        mov     10[bx+di],dx    ; store the new value
        mov     bx,dx           ; convert number addr to number
        mov     al,[bx]         ; /
        tohex                   ; convert it to ascii hex
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        mov     es:[bx],ah      ; display number
        mov     es:2[bx],al     ; /
        mov     al,blue+hi      ; set color to blue (may have been green)
        mov     es:1[bx],al     ;  /
        mov     es:3[bx],al     ; /
        ;
        mov     curonf,1        ; don't restore
        call    curon           ; normal cursor
        mov     doesc,offset work71; set up for ESC
        mov     al,curcol       ; save cursor color
        mov     savcol,al       ; /
        mov     ax,3            ; get current position
        int     33h             ; /
        mov     ax,7            ; don't move cursor
        push    dx              ;       /
        mov     dx,cx           ;      /
        int     33h             ;     /
        pop     dx              ;    /
        mov     cx,dx           ;   /
        mov     ax,8            ;  /
        int     33h             ; /
        mov     curcol,0        ; hide the cursor
        mov     valflg,1        ; flag value input is happening
        jmp     workx           ; back to the work loop
;--------------------------------------------------------------
; escape from value input command
;
work71: mov     di,tmpsav       ; turn off highlight
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        and     byte ptr es:1[bx],lo; zip hilight
        and     byte ptr es:3[bx],lo; /
        mov     al,savcol       ; restore cursor color
        mov     curcol,al       ;     /
        mov     dx,199          ; maximum y
        mov     cx,0            ; minimum y
        mov     ax,8            ; set min, max allowable pdy values
        int     33h             ; /
        mov     ax,7            ; set min, max allowable pdx values
        mov     dx,639          ; maximum x
        mov     cx,0            ; minimum x
        int     33h             ; set it
        mov     es,vpage        ; lowlight the menu readout        
        mov     bx,960H         ; addr of decimal readout
        mov     byte ptr es:1[bx],blue ; make dark  
        mov     byte ptr es:3[bx],blue ;   /
        mov     byte ptr es:5[bx],blue ;  /
        mov     byte ptr es:7[bx],blue ; /
        mov     bx,0A00H        ; addr of note readout
        mov     byte ptr es:1[bx],blue ; make dark  
        mov     byte ptr es:3[bx],blue ;   /
        mov     byte ptr es:5[bx],blue ;  /
        mov     byte ptr es:7[bx],blue ; /
        mov     curonf,1        ; don't restore under cursor
        mov     valflg,0        ; finished with value input
        ret
;--------------------------------------------------------------
; case of pdf = 0, cmdflg = 7, and change in pdx,pdy
; process value input from user
;
work72: call    curoff          ; cursor off
        mov     bx,holdv        ; get offset to the value
        mov     di,tmpsav       ; get value table for module
        mov     bx,10[bx+di]    ; get adr of current value
        mov     dx,mickx        ; get mickey count
        add     dx,[bx]         ; add value to mickeys
        jz      work72b         ; if = 0, go on
        cmp     dx,255          ; if = 255, go on
        jz      work72b         ; /
        test    dh,128          ; if neg, make it 0
        jz      work72a         ; /
        mov     dx,0            ; /
work72a:test    dh,1            ; if > 255, make it 255
        jz      work72b         ;  /
        mov     dx,255          ; /
work72b:add     dx,dx           ; make into a word
        mov     di,tmpsav       ; get value table for module
        add     dx,offset dgroup:@zero; dx = address pointer into number table
        mov     bx,holdv        ; get offset to the value
        mov     10[bx+di],dx    ; store the new value
        mov     bx,dx           ; convert number addr to number
        mov     al,[bx]         ; /
        push    ax              ; save for decimal conversion
        tohex                   ; convert it to ascii hex
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        mov     es:[bx],ah      ; display number
        mov     es:2[bx],al     ; /
        mov     al,blue+hi      ; set color to blue (may have been green)
        mov     es:1[bx],al     ;  /
        mov     es:3[bx],al     ; /
        mov     bx,960H         ; address of decimal readout
        mov     colr,blue+hi    ; set highlight blue
        pop     ax              ; get the number again
        call    todec           ; show it in decimal
        mov     bx,0A00h        ; address of note readout
        call    tonote          ; show it as CM scale
        mov     curonf,1        ; don't restore cursor
        call    curon           ; turn it back on
work72x:jmp     workx           ; exit
;==============================================================
; Special User input selected, set cmdflg = 9
; magflg gets set here:
;       no-value--> 0
;       up/down --> 1
;       channel --> 2
;       value   --> 3
;
work90: mov     cmdflg,9        ; else set the flag for channel value
        call    curoff          ; turn cursor off
        mov     di,varnow       ; get variable table address
        mov     tmpsav,di       ; save it
        mov     varsav,di       ; save it
        mov     bx,[di]         ; get exe addr of special routine
        mov     ax,40[bx]       ; ax = exec addr of special
        mov     special,ax      ; save it
        mov     bx,cmdloc       ; highlight the command
        mov     locsav,bx       ; (save hilight addr)
        mov     es,vpage        ;        /
        mov     magflg,0        ; set flag for no-value
        cmp     byte ptr es:[bx],'#'; is this a no-value cmd
        jz      work90b         ; yes, set up for no-value
        inc     magflg          ; no, set flag for up/down
        cmp     byte ptr es:[bx],1eh; branch if up/down
        jz      work90b         ; /
        or      byte ptr es:1[bx],hi; highlight single for channel
        inc     magflg          ; set magenta flag for channel
        cmp     byte ptr es:3[bx],white; is this a channel cmd
        jz      work90b         ; yes, branch
        inc     magflg          ; no, set up for value change
        or      byte ptr es:3[bx],hi; highlight double for value
work90b:mov     ax,0            ; find out which value it is
work90a:sub     bx,160          ;       /
        add     ax,2            ;     /
        cmp     byte ptr es:1[bx],magenta
        jz      work90a         ; /
        mov     holdv,ax        ; save the offset
        mov     curonf,1        ; don't restore
        call    curon           ; normal cursor
        cmp     magflg,3        ; want value input?
        jnz     work90x         ; no, exit
        mov     al,curcol       ; save cursor color
        mov     savcol,al       ; /
        mov     ax,3            ; get current position
        int     33h             ; /
        mov     ax,7            ; don't move cursor
        push    dx              ;       /
        mov     dx,cx           ;      /
        int     33h             ;     /
        pop     dx              ;    /
        mov     cx,dx           ;   /
        mov     ax,8            ;  /
        int     33h             ; /
        mov     curcol,0        ; hide the cursor
work90x:mov     doesc,offset work91 ; set up for ESC
        mov     usrflg,1        ; flag user input is happening
        mov     ax,special      ; get the special routine
        call    ax              ; do it
        jmp     workx           ; back to the work loop
;--------------------------------------------------------------
; escape from special user command
;
work91: mov     usrflg,0        ; clear happening flag
        cmp     magflg,3        ; data input
        jnz     work91a         ; no, branch
        jmp     work71          ; yes, same as blue
        ;
work91a:mov     di,varsav       ; turn off highlight
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        and     byte ptr es:1[bx],lo; zip hilight
        mov     ax,offset noop  ; reset special
        mov     special,ax      ; /
        mov     curonf,1        ; don't restore cursor
        ret                     ; return from call
;--------------------------------------------------------------
; process special user input routine
;
work9:  mov     cmdflg,0
        mov     usrflg,0
        mov     ax,special
        jmp     ax
;--------------------------------------------------------------
; special user input routines
; case of pdf = 0, cmdflg = 9, and change in pdx,pdy
; process value input from user
;
work92: cmp     magflg,2        ; want channel?
        jz      work92a         ; yes, branch
        cmp     magflg,3        ; want data?
        jz      work92e         ; yes, branch
        jmp     workx           ; no, exit

work92a:mov     dl,pdx          ; get x value
        sub     dl,8            ; offset by 8
        jnb     work92d         ; branch if ok
        mov     dl,0            ; else set to 0
work92d:cmp     dl,63           ; max is 63
        jna     work92b         ; branch if ok
        mov     dl,63           ; else max out
work92b:shr     dl,1            ; /4
        shr     dl,1            ; /
        and     dl,0fH          ; only use low nybble
        mov     al,dl           ; load with x value
        mov     di,varsav       ; get value table for module
        mov     byte ptr 8[di],dl; save in the output location
        tohex                   ; convert it to ascii hex
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        mov     es:[bx],al      ; display number
        ;
        jmp     workx           ; exit

work92e:
        call    curoff          ; cursor off
        mov     bx,holdv        ; get offset to the value
        mov     di,varsav       ; get value table for module
        mov     dl,10[bx+di]    ; get current value
        mov     dh,0            ; /
        add     dx,mickx        ; get mickey count
        jz      work92g         ; if = 0, go on
        cmp     dx,255          ; if = 255, go on
        jz      work92g         ; /
        test    dh,128          ; if neg, make it 0
        jz      work92f         ; /
        mov     dx,0            ; /
work92f:test    dh,1            ; if > 255, make it 255
        jz      work92g         ;  /
        mov     dx,255          ; /
work92g:mov     di,varsav       ; get value table for module
        mov     bx,holdv        ; get offset to the value
        mov     10[bx+di],dl    ; store the new value
        mov     ax,dx           ; get value to ax
        push    ax              ; save for decimal conversion
        tohex                   ; convert it to ascii hex
        mov     es,4[di]        ; get seg
        mov     bx,locsav       ; get addr
        mov     es:[bx],ah      ; display number
        mov     es:2[bx],al     ; /
        mov     colr,magenta+hi ; set hilighted magenta
        pop     ax              ; get the number again
        mov     bx,960H         ; address of decimal readout
        call    todec           ; show it in decimal
        mov     bx,0A00h        ; address of note readout
        call    tonote          ; show it as CM scale
        mov     curonf,1        ; don't restore cursor
        call    curon           ; turn it back on
        jmp     workx           ; exit

;==============================================================
; have been dragging a module around, now want to do something with it
;
work2a: call    setcur          ; set normal cursor again
        call    curoff          ; and then turn it off
work2b: cmp     vpagen,0        ; now in page 0 ?
        jnz     work2b1         ; no, continue
        jmp     work3           ; yes, go get a new module
work2b1:cmp     cmdflg,1        ; was last command "create module"?
        jz      work2c          ; yes, go do it
        cmp     cmdflg,2        ; no, was it "copy module"?
        jz      work2b2         ; yes, go do it
        jmp     work5           ; no, go do "reincarnate module" 
work2b2:jmp     work4           ; go do "copy module"
;==============================================================
; Want to create a new module.  Check that there is enough empty
; space on the screen, and if ok, draw the module.
;
work2c: mov     es,vpage        ; pick up video page segment
        mov     bx,curadr       ; current cursor offset
        mov     di,modchar      ; point to module char source
        mov     cx,[di]         ; get the line count
        mov     ax,0            ; clear register
work2f: or      al,es:1[bx]     ; look to see that there is space
        or      al,es:-1[bx]    ;       /
        or      al,es:3[bx]     ;     /
        add     bx,160          ;   /
        loop    work2f          ; /  
        or      al,al           ; was there?
        jz      work2g          ; yes, branch
        call    setmod          ; no, continue dragging the module around
        jmp     workx           ; back to work
;--------------------------------------------------------------
; There is enough space on the screen, show the module
;
work2g: mov     cmdflg,0        ; clear the command flag
        mov     cx,[di]         ; get module line count again
        add     di,4            ; point to 1st char
        mov     bx,curadr       ; cursor address
        dec     bx              ; shift for module
        dec     bx              ; /
        call    shomod$         ; show the module
        mov     bx,curadr       ; cursor address
        mov     ax,last         ; get priority
        showp                   ; show priority
;--------------------------------------------------------------
; set up exetbl enteries, variable space, and pointers thereto
;
        mov     bx,offset dgroup:_exetbl; calc addr of last module
        mov     ax,last         ;       /
        add     ax,ax           ;     /
        add     ax,ax           ;   /
        add     bx,ax           ; /
        mov     di,cmdptr       ; get address of modsrc table
        mov     ax,[di]         ; get module exe addr
        mov     [bx],ax         ; put it in exetbl
        mov     ax,varptr       ; get end of variable table
        mov     2[bx],ax        ; put it in exetbl
        mov     ax,offset work  ; get exe addr of work
        mov     4[bx],ax        ; put it at the end of the exetbl
        mov     ax,4[di]        ; get variable allocation for module
        mov     dx,ax           ; (dx=variable allocation)
        add     ax,ax           ; *2 for word
        add     ax,14           ; plus static allocation
        mov     bx,varptr       ; get current variable address
        add     ax,bx           ; ax = next one, bx = this one
        mov     varptr,ax       ; set varptr to new end of list
;--------------------------------------------------------------
; build the variable list
;
        mov     [bx],di         ; first word is modsrc addr
        mov     ax,last         ; get priority
        mov     2[bx],ax        ; second word is priority
        push    bx              ; save variable list pointer for later
        inc     ax              ; bump index
        and     ax,maxmods      ; limit to 512 active modules
        mov     last,ax         ; store it
        mov     ax,vpage        ; current display seg addr
        mov     4[bx],ax        ; third word is vpage seg address
        mov     ax,curadr       ; current head of module text
        mov     6[bx],ax        ; forth word is addr of module label
        mov     word ptr 8[bx],0; fifth word is module output
        mov     10[bx],dx       ; sixth word is variable alloc count
        add     bx,12           ; point to start of variables
        mov     cx,4[di]        ; get number of variables allocated
        or      cx,cx           ; got at least one?
        jnz     work2h          ; yes, branch
        inc     cx              ; always make at least one
work2h: mov     word ptr [bx], offset dgroup:@zero; set variables to zero
        inc     bx              ; point to next
        inc     bx              ; /
        loop    work2h          ; loop til done
        mov     bx,-2           ; find out the module number
work2i: add     bx,2            ;      /
        cmp     word ptr 6[bx+di],0; /
        jnz     work2i          ; bx = module number *2
        mov     ax,bx           ; get actual number
        shr     ax,1            ; /
        mov     modnum,al       ; save it for the other guys
        pop     ax              ; get variable list ptr from stack
        mov     6[bx+di],ax     ; put it in modsrc
        mov     di,2[di]        ; get source text for the module
;        mov     bx,2[di]        ; get page 0 address
        mov     bx,cmdtag       ; get page 0 address
        mov     ax,0b800H       ; page 0 segment
        mov     es,ax           ; set up seg reg for page 0
        mov     al,byte ptr es:2[bx]; get the current module number
        mov     ah,al           ; copy it
        inc     ah              ; bump
        cmp     al,'$'          ; system module?
        jnz     work2j          ; no, branch
        mov     ah,'*'          ; yes, show "in use"
work2j: cmp     ah,':'          ; did it go from 9->10?
        jnz     work2k          ; no, branch
        mov     ah,'A'          ; yes, funky hex conversion
work2k: cmp     ah,'G'          ; >16?
        jnz     work2l          ; no, branch
        mov     ah,'*'          ; yes, show "in use"
work2l: mov     byte ptr es:2[bx],ah; set new module number
        mov     byte ptr 8[di],ah; set it in the source
;--------------------------------------------------------------
; finish up by turning on the regular cursor, going back to work
;
        mov     curonf,1        ; don't restore old cursor
        call    curon           ; normal cursor
        jmp     workx           ; back to the grind
;==============================================================
; command was "create", now another page 0 module is selected,
; zip pending command, kill module cursor
;
work3:  cmp     cmdflg,2        ; stray move?
        jnz     work3a          ; no, branch
        jmp     cancel          ; yes, cancel the command
work3a: mov     cmdflg,0        ; zip pending command
        mov     curonf,1        ; don't restore old cursor
        call    curon           ; drop module and exit
        jmp     workx           ; ...back to the work loop
;==============================================================
; Want to move an existing module.  Check that there is enough empty
; space on the screen, and if ok, draw the module.
; 
work4:  mov     es,vpage        ; pick up video page segment
        mov     bx,curadr       ; current cursor offset
        mov     di,modchar      ; point to module char source
        mov     cx,[di]         ; get the line count
        mov     al,0            ; clear register
work4a: test    byte ptr es:1[bx],80h ; look to see that there is space
        jnz     work4aa         ; blinking counts as 0
        or      al,es:1[bx]     ;                 /
work4aa:test    byte ptr es:-1[bx],80h;         /
        jnz     work4ab         ;             /
        or      ax,es:-1[bx]    ;           /
work4ab:test    byte ptr es:3[bx],80h;    /
        jnz     work4ac         ;       /
        or      ax,es:3[bx]     ;     /
work4ac:add     bx,160          ;   /
        loop    work4a          ; /  
        or      al,al           ; the final test
        jz      work4b          ; nothing there, branch to the move
        call    setmod          ; else continue dragging the module around
        jmp     workx           ; back to work
;--------------------------------------------------------------
; There is enough space, erase the old module, 
; then display it in its new location.
; First find old module's location page.
; 
work4b: mov     di,tmpsav       ; get varlist of source module
        mov     es,4[di]        ; get seg of source module display
        mov     bx,6[di]        ; get offset of tag
;--------------------------------------------------------------
; Now erase the old module.
;
        mov     di,[di]         ; di = modsrc(old_varlist)
        mov     di,2[di]        ; di = txtadr(modsrc(old_varlist))
        mov     cx,[di]         ; cx = line count
        call    eramod$         ; erase the old module
;--------------------------------------------------------------
; Show the module in its new location
;
        mov     cmdflg,0        ; clear the command flag
        mov     di,modchar      ; point to module char source
        mov     cx,[di]         ; get module line count again
        add     di,4            ; point to 1st char
        mov     bx,curadr       ; cursor address
        dec     bx              ; shift for module
        dec     bx              ; /
        mov     es,vpage        ; get current screen seg addr
        call    shomod$         ; show the module
;--------------------------------------------------------------
; set new screen location in the variable list
;
        mov     di,tmpsav       ; get varlist of source module
        mov     ax,vpage        ; get current seg
        mov     4[di],ax        ; put it in the list
        mov     ax,curadr       ; get cursor addr
        mov     6[di],ax        ; in the list
;--------------------------------------------------------------
; finish up by turning on the regular cursor, going back to work
;
work4x: mov     curonf,1        ; don't restore old cursor
        call    curon           ; normal cursor
        jmp     workx           ; back to the grind
;==============================================================
; Have been dragging a gost around, now it's time to reincarnate.
; Check that there is enough empty space on the screen.
;
work5:  mov     es,vpage        ; pick up video page segment
        mov     bx,curadr       ; current cursor offset
        mov     di,modchar      ; point to module char source
        mov     cx,[di]         ; get the line count
        mov     ax,0            ; clear register
work5a: or      al,es:1[bx]     ; look to see that there is space
        or      al,es:-1[bx]    ;       /
        or      al,es:3[bx]     ;     /
        add     bx,160          ;   /
        loop    work5a          ; /  
        or      al,al           ; was there?
        jz      work5b          ; yes, branch
        call    setmod          ; no, continue dragging the module around
        jmp     workx           ; back to work
;--------------------------------------------------------------
; There is enough space.  Get a delete flag from MODSRC,
; Use it as a pointer to the variable list.
;
work5b: mov     di,tmpsav       ; get last modsrc
        mov     ax,38[di]       ; get the bit flags
        call    frombit         ; convert to a number
        push    ax              ; save a copy for later
        mov     bx,ax           ; convert to an address offset
        add     bx,bx           ; /
        mov     bx,6[bx+di]     ; bx = address of the variable table
        call    tobit           ; mask out the reincarnated bit
        xor     ax,-1           ;   /
        and     38[di],ax       ; /
        jnz     work5c          ; branch if there are more delete flags
;--------------------------------------------------------------
; no more delete flags, fix 'X'
;
        push    bx              ; save variable table pointer
        mov     bx,-2           ; find out the module number
work5d: add     bx,2            ;      /
        cmp     word ptr 6[bx+di],0; /
        jnz     work5d          ; bx = module number *2
        shr     bx,1            ; /2
        mov     al,'*'          ; load
        cmp     bl,16           ; last module?
        jz      work5e          ; yes, branch using '*'
        mov     al,bl           ; no, use the module number
        tohex                   ; convert to ascii hex
work5e: mov     bx,2[di]        ; find text address
        mov     bx,2[bx]        ; bx = page0 screen offset
        mov     dx,0b800h       ; set page0 seg
        mov     es,dx           ; /
        cmp     word ptr 36[di],-1; system module?
        jnz     work5e0         ; no, branch
        mov     al,'*'          ; yes, use * instead of number 
work5e0:mov     es:4[bx],al     ; set the module number
        pop     bx              ; restore the variable table addr
;--------------------------------------------------------------
; restore the original module number and priority number
;
work5c: mov     dx,2[bx]        ; get priority number
        pop     ax              ; get the module number
        tohex                   ; convert to ascii hex
        push    bx              ; save the variable table addr
        mov     bx,modchar      ; point to $dummy
        cmp     word ptr 36[di],-1; system module?
        jnz     work5c0         ; no, branch
        mov     al,'$'          ; yes, use $ instead of number 
work5c0:mov     8[bx],al        ; set the current module number
        mov     ax,dx           ; get lsb of priority number
        and     ah,1            ; do ms byte
        xor     ah,1            ;   /
        add     ah,0f8h         ;  /
        mov     10[bx],ah       ; /
        tohex                   ; convert to ascii hex
        mov     12[bx],ah       ; set the priority number
        mov     14[bx],al       ; /
        pop     bx              ; restore variable table addr
;--------------------------------------------------------------
; update the variable table
;
        mov     ax,vpage        ; get current seg addr
        mov     4[bx],ax        ; put in seg slot of var table
        mov     ax,curadr       ; current cursor offset
        mov     6[bx],ax        ; put in addr slot of var table
        mov     cx,10[bx]       ; get number of variables allocated
        or      cx,cx           ; don't do it if 0 variables
        jz      work5f          ; /
        push    bx              ; save variable pointer
work5g: mov     word ptr 12[bx], offset dgroup:@zero; set variables to zero
        inc     bx              ; point to next
        inc     bx              ; /
        loop    work5g          ; loop til done
        pop     bx              ; restore variable pointer
work5f: mov     word ptr 8[bx],0; set output to 0
;--------------------------------------------------------------
; reactivate by inserting the module exe addr in the exe table
;
        mov     di,[bx]         ; get modsrc addr
        mov     di,[di]         ; di = exe addr of module
        mov     bx,2[bx]        ; get priority
        add     bx,bx           ; *4
        add     bx,bx           ; /
        add     bx,offset dgroup:_exetbl;bx = addr position in exetbl
        mov     [bx],di         ; replace dummy with the real one
;--------------------------------------------------------------
; Show the module in its new location
;
        mov     cmdflg,0        ; clear the command flag
        mov     di,modchar      ; point to module char source
        mov     cx,[di]         ; get module line count again
        add     di,4            ; point to 1st char
        mov     bx,curadr       ; cursor address
        dec     bx              ; shift for module
        dec     bx              ; /
        mov     es,vpage        ; get current screen seg addr
        call    shomod$         ; show the module
;--------------------------------------------------------------
; finish up by turning on the regular cursor, going back to work
;
work5x: mov     curonf,1        ; don't restore old cursor
        call    curon           ; normal cursor
        jmp     workx           ; back to the grind
;==============================================================
; Priority swap was pending, now do it.
;
work6:  call    curoff          ; turn cursor off
        mov     bx,tmpsav       ; get saved variable table
        mov     es,4[bx]        ; get seg of last screen
        mov     bx,6[bx]        ; get offset of last screen
        mov     byte ptr es:161[bx],grey; turn off hilight
        mov     byte ptr es:163[bx],grey; /
        ;
        mov     di,tmpsav       ; old variable table
        mov     si,varnow       ; new variable table
        mov     ax,2[di]        ; get old priority #
        mov     dx,ax           ; dx = old priority #
        xchg    ax,2[si]        ; swap with new
        mov     2[di],ax        ; /
        ;
        add     ax,ax           ; convert to exetbl addr
        add     ax,ax           ; /
        add     ax,offset dgroup:_exetbl; ax = new exetbl addr
        mov     bx,ax           ; bx = new exetbl addr
        mov     ax,[bx]         ; ax = new exe addr
        mov     cx,2[bx]        ; cx = new vartbl addr
        add     dx,dx           ; convert old # to exetbl addr
        add     dx,dx           ; /
        add     dx,offset dgroup:_exetbl; dx = old exetbl addr
        mov     bp,dx           ; bp = old exetbl addr
        xchg    ax,ds:[bp]      ; swap exe addrs
        mov     [bx],ax         ; /
        xchg    cx,ds:2[bp]     ; swap vartbl addrs
        mov     2[bx],cx        ; /     
        ;
        mov     es,4[si]        ; get screen seg of new
        mov     bx,6[si]        ; get screen addr of new
        mov     ax,2[si]        ; get priority #
        showp                   ; show priority
        mov     es,4[di]        ; get screen seg of old
        mov     bx,6[di]        ; get screen addr of old
        mov     ax,2[di]        ; get priority #
        showp                   ; show priority
        ;
        mov     cmdflg,0        ; clear the command
        mov     curonf,1        ; don't restore
        call    curon           ; normal cursor
        jmp     workx           ; back to the work loop
;==============================================================
; Delete Module was pending, now it's time to do it.
;
workpa: cmp     vpage,0         ; page 0 ?
        jnz     workpa0         ; no, branch
        jmp     workpz          ; yes, exit
        ;
workpa0:test    cmdcol,80H      ; valid color
        jnz     workpz          ; no, exit
        ;
        mov     bx,5a0h         ; offset for DEL
        call    turnoff         ; turn off highlight
        call    curoff          ; turn off cursor
        ;
        mov     di,cmdptr       ; find out which module #
        mov     bx,0            ; counter offset
        mov     ax,varnow       ; get current variable list
workpb: cmp     6[di+bx],ax     ; look for a match
        jz      workpc          ; branch if found
        add     bx,2            ; else bump index
        cmp     bx,32           ; split if not found
        jz      workpx          ; /
        jmp     short workpb    ; loop
        ;                       ; bx = module # *2
workpc: mov     al,bl           ; al = module # *2
        shr     al,1            ; al = module #
        call    tobit           ; ax = bit pattern
        or      38[di],ax       ; flag module as deleted
        mov     di,varnow       ; get variable list
        mov     bx,2[di]        ; get priority
        add     bx,bx           ; *4
        add     bx,bx           ; /
        add     bx,offset dgroup:_exetbl; point to position in exetable
        mov     word ptr [bx],offset _dummy ; insert dummy
        ;                       ; set up to erase the module from screen
        mov     es,4[di]        ; get seg of module display
        mov     bx,6[di]        ; get offset of tag
        ;
        mov     word ptr 4[di],0b000H; set illegal display seg
        mov     word ptr 6[di],-1; set illegal display offset
        ;
        mov     di,[di]         ; di = modsrc(varlist)
        mov     di,2[di]        ; di = txtadr(modsrc(varlist))
        mov     cx,[di]         ; cx = line count
        call    eramod$         ; erase the old module
        ;                       ; mark source as erased
        mov     di,cmdptr       ; get source text
        mov     di,2[di]        ; di = txtadr(modsrc(cmdptr)))
        mov     bx,2[di]        ; bx = screen address of source text
        mov     ax,0b800h       ; set page0 seg
        mov     es,ax           ; /
        mov     byte ptr es:4[bx],'X' ; mark source as deleted
        ;                       ; finish up and exit
workpx: mov     curonf,1        ; don't restore under cursor
        call    curon           ; cursor back on
        mov     cmdflg,0        ; clear command flag
workpz: jmp     workx           ; exit
;==============================================================
; End of WORK.  If not HLT'd or module cursor, reset SI to the head
; of the module list, and run through the modules again.
;
        public  workx
workx:
        test    midixsf,1       ; external sync input?
        jz      workxa          ; no, branch
        mov     al,midixs       ; yes, get xtrn sync
        cmp     al,midiss       ; same as before?
        jz      workxx          ; yes, back to loop
        mov     midiss,al       ; no, reset saved count
        mov     tickis,al       ; set alpha display
        jmp     short workx2    ; go to work
        ;
workxa:
        test    asensf,-1       ; want active sensing?
        jz      workxas         ; no, branch
        test    byte ptr ticks,7fh; time for active sensing?
        jnz     workxas         ; branch if not needed yet
        mov     al,0feh         ; send MIDI active sensing
        call    allmidi         ; /
workxas:sendmb
        ;
        test    fastflg,-1      ; fast flag set
        jnz     workx4          ; yes, branch
        test    byte ptr cs:timer,255; timer zeroed out?
        jz      workx4          ; yes, branch
        test    waiting,-1      ; have been waiting?
        jnz     workxx          ; yes, do housekeeping again
        mov     waiting,1       ; no, set flag
        mov     al,byte ptr cs:timer; get current timer value
        mov     tickis,al       ; save it
workxx: sendmb                  ; send midi byte, if any
        jmp     work            ; go do housekeeping
        ;
workx4: mov     al,ticka        ; get new timer value
        mov     byte ptr cs:timer,al; put it in the timer
        test    waiting,-1      ; was waiting?
        jnz     workx2          ; yes, branch
        mov     tickis,0        ; no, zip tick readout
workx2: mov     waiting,0       ; not waiting now
        ;
workx0: cmp     mmreset,0       ; want to reset measures?
        jnz     workx5          ; no, branch
        mov     mmcount,0       ; yes, reset measure count
        mov     mmreset,0       ; clear flag on sync
        jmp     short workx6    ; set new measure
        ;
workx5: mov     mmstart,0       ; flag not end of measure
        dec     mmtick          ; kick measure timer
        jnz     workx3          ; branch if really not eom
workx6: mov     ax,mclocks      ; else reload timer
        mov     mmtick,ax       ; /
        mov     mmstart,1       ; flag start of measure
        inc     mmcount         ; bump measure count
        mov     ax,mmcount      ; else display measure count
        mov     bx,vpage        ; current video page
        mov     es,bx           ; /
        mov     bx,160*13       ; address of decimal readout
        call    toddec          ; display
        ;
workx3: ;
        test    secondf,-1      ; new seconds count?
        jz      workx9          ; no, branch
        mov     secondf,0       ; yes, clear the flag
        mov     ax,seconds      ; display seconds count
        mov     bx,vpage        ; current video page
        mov     es,bx           ; /
        mov     bx,160*14       ; address of decimal readout
        call    toddec          ; display
        ;
workx9: test    lodflg,-1       ; lodflg aready 0
        jz      workx9a         ; yes, do nothing
        dec     lodflg          ; else dec the flag
        ;
workx9a:test    clrchf,2        ; channel cleared? 
        jz      workx7          ; no, branch
        mov     clrchf,0        ; yes, clear flag
        ;
workx7: cmp     pdx,3           ; in menu area
        jnb     workx7e         ; no, branch
        cmp     pdy,17          ; in mute area
        jb      workx7e         ; no, branch
workx7e:mov     bx,vpage        ; get video page
        mov     es,bx           ; es = current video page
        mov     bx,160*17       ; point to menu area
        inc     bx              ; point to highlight byte
        mov     dx,mute         ; get mute flags
        mov     al,hi           ; hi  if not mute
        mov     ah,lo           ; lo if mute
        mov     cx,8            ; 8 * 2 mute flags
workx7l:ror     dx,1            ; pop even flag
        jc      workx7a         ; branch if mute
        or      es:[bx],al      ; set hi  if not mute
        jmp     short workx7b   ; branch
workx7a:and     es:[bx],ah      ; set lo if mute
workx7b:ror     dx,1            ; pop odd flag 
        jc      workx7c         ; branch if mute
        or      es:4[bx],al     ; set hi  if not mute
        jmp     short workx7d   ; branch
workx7c:and     es:4[bx],ah     ; set lo if mute
workx7d:add     bx,160          ; next line
        loop    workx7l         ; do 8 pairs
        ;
        test    midisf,1        ; midi sync flag on?
        jz      workx8a         ; no, branch
        mov     al,0f8h         ; yes, send one
        mov     midip,0         ; ... only to port 0
        call    tomidi          ; /
        ;
workx8a:inc     cs:loops        ; inc loop counter
        mov     si,offset dgroup:_exetbl; point to start of table
        mov     di,2[si]        ; set di pointing to variable list
        jmp     [si]            ; go for it
;--------------------------------------------------------------
; cleanup & exit
        public  split
split:  call    curoff          ; turn pd cursor off
split1: mov     dx,seg dgroup   ; set up ds
        mov     ds,dx           ; /
        mov     al,0            ; set vpage0
        call    page            ;
        call    cls             ; clear screen
        mov     ah,2            ; set cursor to top of screen
        mov     dx,0            ;     /
        mov     bh,dh           ;   /
        int     10H             ; /
        mov     ah,1            ; turn dos cursor on
        mov     ch,6            ;     /
        mov     cl,7            ;   /
        int     10H             ; /
        call    stopt           ; stop system timer
        call    stopm           ; stop mpu ints
        ;
        mov     dx,byemsg       ; get exit message
        or      dx,dx           ; anything there
        jz      split2          ; no, branch
        mov     ah,9            ; dos print string
        int     21h             ; dos call
split2: ;
        if      withc           ; if compiled with C
        pop     di              ; restore C regs
        pop     si              ;     /
        pop     bp              ;   /
        pop     es              ; /
        ret                     ; back to C
        else                    ; if assembley
        ;
        mov     ax,4c00h        ; then do assembly exit
        int     21h             ; split
        endif
;==============================================================
; routines used by WORK
;--------------------------------------------------------------
; Return to di the varlist for the currently selected module.
; Assumes the current module tag address is in CMDTAG, and
; the current page address is in VPAGE. Error if DI = 0 on return.
;
varlst: mov     bp,offset dgroup:_exetbl ; point to start of table
        mov     dx,vpage                ; dx = current seg
        mov     cx,cmdtag               ; cx = current module addr
varlst0:mov     di,0                    ; err if 0 returned
        cmp     word ptr ds:[bp],offset work; exit when list is exausted
        jz      varlstx                 ; /
        mov     di,ds:2[bp]             ; get the variable list
        cmp     4[di],dx                ; right seg?
        jnz     varlst2                 ; /
        cmp     6[di],cx                ; right address?
        jz      varlstx                 ; yes, exit
varlst2:add     bp,4                    ; bump to next module
        jmp     short varlst0           ; loop
varlstx:ret                             ; exit with di=varlist addr
;--------------------------------------------------------------
; look at color at the cursor (CURADR), if it is one of the
; command colors, set up CMDCOL, CMDCNT, CMDLOC, CMDTAG & CMDPTR,
; otherwise clear CMDCOL and exit with no further action.  
; Normally, this routine will be called only if pdf = 1.
;
cmdchk  proc    near
        mov     es,vpage        ; get screen segment
        mov     bx,curadr       ; get cursor offset
        mov     dl,es:1[bx]     ; get the color
        cmp     dl,white        ; compare against command color list
        jz      cmdchk1         ; branch out if good
        cmp     dl,grey         ;                   /
        jz      cmdchk1         ;                 /
        cmp     dl,cyan         ;               /
        jz      cmdchk1         ;             /
        cmp     dl,cyan OR hi   ;               /
        jz      cmdchk1         ;             /
        cmp     dl,blue         ;           /
        jz      cmdchk1         ;         /
        cmp     dl,green        ;       /
        jz      cmdchk1         ;     /
        cmp     dl,magenta      ;   /
        jz      cmdchk1         ; /
        or      dl,80H          ; not on list, flag ng color
        mov     cmdcol,dl       ; /
        ret                     ; exit
cmdchk1:mov     cmdcol,dl       ; is good, set the color
        cmp     dl,es:-1[bx]    ; look left
        jnz     cmdchk2         ; branch if not same color
        dec     bx              ; else bump address left
        dec     bx              ; /
cmdchk2:mov     cmdloc,bx       ; save the location
        mov     cmdcnt,0        ; default count is 0
        cmp     dl,blue         ; check for blue or green
        jz      cmdchk3         ;     /
        cmp     dl,green        ;   /
        jz      cmdchk3         ; /
        cmp     dl,magenta      ; check for magenta
        jnz     cmdchk3         ; no, go on
        cmp     curadr,0f9ch    ; test for lower left
        jnb     cmdchk4         ; /
        cmp     byte ptr es:5[bx],white ; left of top label?
        jnz     cmdchk4         ; no, branch
        add     bx,2            ; yes, bump to label
        jmp     short cmdchk4   ; branch around count
        ;
cmdchk3:mov     dh,-1           ; blue or green needs count
cmdchk5:inc     dh              ; dh = count
        sub     bx,160          ; up one line
        cmp     byte ptr es:1[bx],blue; look for blue or green
        jz      cmdchk5         ;         /                        
        cmp     byte ptr es:1[bx],green;/                      
        jz      cmdchk5         ; look until color not blue or green
        cmp     byte ptr es:1[bx],magenta
        jz      cmdchk5         ; look until color not magenta
        mov     cmdcnt,dh       ; set the count
        mov     bx,cmdloc       ; restore bx
cmdchk4:cmp     byte ptr es:1[bx],white; look for white
        jz      cmdchk6         ; exit loop when found
        sub     bx,160          ; back one line
        jmp     short cmdchk4   ; /
cmdchk6:mov     cmdtag,bx       ; save the tag address
        mov     al,byte ptr es:[bx] ; get the character
        mov     ah,0            ; make it into an address
        add     ax,ax           ; /
        mov     di,offset dgroup:_chrtbl; find the ptr for that char
        add     di,ax           ;     /
        mov     ax,[di]         ;   /
        mov     cmdptr,ax       ; /
        ret                     ; exit
cmdchk  endp

;--------------------------------------------------------------
; use module text for cursor
;
setmod  proc    near
        call    curoff          ; turn off regular cursor
        mov     di,modchar      ; get line size
        mov     ax,[di]         ; /
        add     ax,ax           ; convert to pixel addr
        add     ax,ax           ;   /
        add     ax,ax           ; /
        mov     dx,200          ; subtract from max
        sub     dx,ax           ; dx = maximum pdy for this char
        mov     cx,0            ; 0  = minimum pdy
        mov     ax,8            ; set min, max allowable pdy values
        int     33h             ; /
        mov     ax,7            ; set min, max allowable pdx values
        mov     dx,631          ; maximum x
        mov     cx,8            ; minimum x
        int     33h             ; set it
        ;
        mov     execur,offset modcur; do show-modules
        mov     curflg,1        ; flag special cursor
        call    curon           ; continue
        ret
setmod  endp
;--------------------------------------------------------------
; use module text for cursor
;
setcur  proc    near
        call    curoff          ; stop pd interupts
        mov     dx,199          ; maximum y
        mov     cx,0            ; minimum y
        mov     ax,8            ; set min, max allowable pdy values
        int     33h             ; /
        mov     ax,7            ; set min, max allowable pdx values
        mov     dx,639          ; maximum x
        mov     cx,0            ; minimum x
        int     33h             ; set it
        ;
        mov     execur,0        ; no special cursors
        mov     curflg,0        ; /
        call    curon           ; continue
        ret
setcur  endp
;--------------------------------------------------------------
; Turn on menu command highlight.
; call with cursor on, bx = menu text offset
;
        public  turnon
turnon: push    bx              ; save text addr
        call    curoff          ; zip cursor
        pop     bx              ; get text addr
        mov     dx,0b800h       ; do all 8 pages
        mov     cx,8            ; /
turnon1:mov     es,dx           ; set the page seg
        or      byte ptr es:1[bx],8 ; make bright
        or      byte ptr es:3[bx],8 ;   /
        or      byte ptr es:5[bx],8 ; /
        inc     dh              ; next page
        loop    turnon1         ; loop til done 
        mov     curonf,1        ; don't restore 
        jmp     curon           ; cursor normal
;--------------------------------------------------------------
; Turn off menu command highlight.
; call with cursor on, bx = menu text offset
;
        public  turnoff
turnoff:push    bx              ; save text addr
        call    curoff          ; zip cursor
        pop     bx              ; get text addr
        mov     dx,0b800h       ; do all 8 pages
        mov     cx,8            ; /
turnoff1:mov    es,dx           ; set the page seg
        and     byte ptr es:1[bx],0f7h ; make dark  
        and     byte ptr es:3[bx],0f7h ;   /
        and     byte ptr es:5[bx],0f7h ; /
        inc     dh              ; next page
        loop    turnoff1        ; loop til done 
        mov     curonf,1        ; don't restore 
        jmp     curon           ; keep it right
;--------------------------------------------------------------
; convert binary in al to decimal in in screen location es:bx
; all registers preserved
;
        public  todec
todec:  push    dx              ; save registers
        mov     dl,al           ;       /
        push    ax              ;     /
        push    bx              ;   /
        push    cx              ; /
        add     bx,4            ; start at ls digit
        mov     cx,3            ; initialize counter
todec1: cmp     dl,0            ; if 0, do shortcut
        jnz     todec0          ; /
        mov     al,30H          ; ascii bias if 0
        jmp     short todec2    ; /
todec0: push    cx              ; save outer loop
        mov     al,dl           ; ax = numerator
        mov     ah,0            ; /
        mov     cl,10           ; divisor of 10
        div     cl              ; divide
        mov     dl,al           ; get quotient
        mov     al,ah           ; get remainder
        add     al,30h          ; add ASCII bias
        pop     cx              ; get loop counter
todec2: mov     es:[bx],al      ; put to the screen
        dec     bx              ; bump count address
        dec     bx              ; /
        loop    todec1          ; do 3 digits
        mov     al,valflg       ; mouse input?
        or      al,usrflg       ; /
        jz      todec3          ; no, branch
        mov     al,colr         ; yes, set color
        mov     es:3[bx],al     ;   /
        mov     es:5[bx],al     ;  /
        mov     es:7[bx],al     ; /
todec3: pop     cx              ; restore registers
        pop     bx              ;     /
        pop     ax              ;   /
        pop     dx              ; /
        ret                     ; exit
;--------------------------------------------------------------
; convert binary in ax to decimal in in screen location es:bx
; all registers preserved
;
        public  toddec
toddec: push    dx              ; save registers
        mov     dx,ax           ;    /
        push    ax              ;   /
        push    bx              ;  /
        push    cx              ; /
        add     bx,4            ; start at ls digit
        mov     cx,3            ; initialize counter
toddec1:mov     ax,dx           ; ax = numerator
        mov     dx,0            ; clear upper half
        cmp     ax,0            ; if 0, do shortcut
        jnz     toddec0         ; /
        mov     al,30H          ; ascii bias if 0
        jmp     short toddec2   ; /
toddec0:push    cx              ; save outer loop
        mov     cx,10           ; divisor of 10
        div     cx              ; divide
        xchg    ax,dx           ; get quotent
        add     al,30h          ; add ASCII bias
        pop     cx              ; get loop counter
toddec2:mov     es:[bx],al      ; put to the screen
        mov     byte ptr es:1[bx],grey
        dec     bx              ; bump count address
        dec     bx              ; /
        loop    toddec1         ; do 3 digits
        pop     cx              ; restore registers
        pop     bx              ;   /
        pop     ax              ;  /
        pop     dx              ; /
        ret                     ; exit
;--------------------------------------------------------------
; convert binary in al to CM scale in screen location es:bx
; all registers preserved
;
        public  tonote
tonote: push    di              ; save registers
        push    ax              ;   /
        push    cx              ; /
        and     al,127          ; 0-127 allowed
        mov     ah,0            ; ax = midi key value
        mov     cl,12           ; 12 notes per octave
        div     cl              ; al = octave, ah = scale
        mov     cl,ah           ; save remainder in cl
        tohex                   ; convert octave to ascii
        mov     es:4[bx],al     ; put to the screen
        mov     ch,0            ; get address of note char
        add     cx,cx           ; /
        add     cx,offset dgroup:cscale
        mov     di,cx           ; di = address of note char
        mov     ax,[di]         ; get the chars
        mov     es:2[bx],al     ; send to the screen
        mov     es:[bx],ah      ; /
        mov     al,valflg       ; mouse input?
        or      al,usrflg       ; /
        jz      tonot0          ; no, branch
        mov     al,colr         ; yes, set color
        mov     es:1[bx],al     ;   /
        mov     es:3[bx],al     ;  /
        mov     es:5[bx],al     ; /
tonot0: pop     cx              ; restore registers
        pop     ax              ;   /
        pop     di              ; /
        ret                     ; exit
;--------------------------------------------------------------
; convert binary in al to hex in ax
; no regs but ax used
;
tohexx: rol     al,1
        rol     al,1
        rol     al,1
        rol     al,1
        mov     ah,al
        and     al,0FH
        daa
        add     al,0F0H
        adc     al,040H
        ;
        xchg    al,ah
        rol     al,1
        rol     al,1
        rol     al,1
        rol     al,1
        and     al,00FH
        daa
        add     al,0F0H
        adc     al,040H
        ret
;--------------------------------------------------------------
; convert hex in al to binary in al
; only al is used
;
fromhex:sub     al,30H          ; for 0-9
        cmp     al,9            ; if 0-9
        jle     fromhxx         ; ... go
        and     al,5fh          ; for lower case
        sub     al,7            ; adjust for A-F
fromhxx:ret
;--------------------------------------------------------------
; convert bit set in ax to nybble in al
; first bit seen is taken
;
frombit:mov     cl,0
        stc
frombi1:inc     cl
        rcr     ax,1
        jnc     frombi1
        dec     cl
        mov     al,cl
        and     ax,15
        ret
;--------------------------------------------------------------
; convert nybble in al to bit set in ax
;
tobit:  mov     cl,al           ; for shift
        mov     ax,1
        shl     ax,cl
        ret
;--------------------------------------------------------------
; convert al to upper case
;
touc:   cmp     al,'a'          ; below lower case chars
        jb      toucx           ; yes, branch
        cmp     al,'z'          ; above lower case chars
        ja      toucx           ; yes, branch
        and     al,5fh          ; mask out bit 5
toucx:  ret
;--------------------------------------------------------------
; Temp HLT set   
; Set clrchf to send out channel module settings
; reset to 1st note in measure
;
tmphlt: or      mprstf,4        ; turn tmp hlt on
        ret
;--------------------------------------------------------------
; Temp HLT clear
; Set HLT highlight according to HLT flag
; Set clrchf to send out channel module settings
; reset to 1st note in measure
;
fixhlt:
        mov     bx,6E0H         ; text offset
        test    mprstf,2        ; was previously halted?
        jnz     fixhlt1         ; yes, turn on highlight
        call    turnoff         ; turn off highlight
        jmp     clrhlt          ; finish up
fixhlt1:
        call    turnon          ; turn on highlight
        ;
clrhlt: and     mprstf,0FBH     ; turn tmp hlt off
        mov     clrchf,1        ; set for chanl module
        mov     mmtick,1        ; reset to 1st note in measure
        ret
;--------------------------------------------------------------
; find module text address on screen 0, and insert them into the
; module source table (_modtxt).  Called once only, on startup.
;
modloc: mov     ax,0b800H       ; set page 0 seg
        mov     es,ax           ; /
        mov     di,0            ; start at offset 0
modlo1: inc     di              ; point to next screen location
        inc     di              ; /
        cmp     di,4090         ; do all of screen 0
        jnz     modlo2          ; branch if not done
        ret                     ; else exit loop
        ;
modlo2: mov     bx,es:[di]      ; get it
        cmp     bh,white        ; look for label color
        jnz     modlo1          ; not interested if not label color
        cmp     bl,'0'          ; not interested if label number
        jz      modlo1          ; /
        cmp     bl,'$'          ; not interested if system module
        jz      modlo1          ; /
        ;
        mov     bh,0            ; bx = label char (0-255)
        add     bx,bx           ; bx = _chrtbl offset
        add     bx,offset dgroup:_chrtbl; add the _chrtbl base address
        mov     bx,[bx]         ; bx = _modsrc address for the label
        mov     bx,2[bx]        ; bx = _modtxt address for the label
        mov     ax,di           ; ax = screen address of the label
        dec     ax              ; drop back two for module address
        dec     ax              ; ax = module address
        mov     2[bx],ax        ; insert module address into table
        jmp     short modlo1    ; loop
;==============================================================
; DOS & BIOS Utilities
;--------------------------------------------------------------
; print string
; call with DX = string addr, terminated with $
;
print$: push    ds
        mov     ax,cs
        mov     ds,ax
        mov     ah,9
        int     21H
        pop     ds
        ret
;--------------------------------------------------------------
; clear current display screen
; cls0 can be called with bh=atrribute
;
cls:    mov     bh,7            ; normal blank
        jmp     short cls0      ; /
clx:    mov     bh,0            ; blank w 0's
cls0:   mov     al,0            ; blank entire page
        mov     ah,7            ; scroll down bios call
        mov     cx,0            ; start at 0,0
        mov     dx,184fH        ; 24, 79
        int     10H             ; do bios thing
        ret                     ; exit
;--------------------------------------------------------------
; set video page
; call with al = video page to be set
; cursor must be off!
;
page:   and     ax,_numpg       ; 0-7 for EGA, 0-3 for CGA
        push    ax              ; save it
        mov     al,vpagep       ; get previous page
        mov     ah,160          ; convert to a screen address
        mul     ah              ;   /
        mov     bx,ax           ; /
        mov     es,vpage        ; get seg of current page
        and     byte ptr es:1[bx],0F7H; return to low yellow
        and     byte ptr es:3[bx],0F7H; /
        mov     al,vpagen       ; get current page
        mov     vpagep,al       ; remember it
        pop     ax              ; get new page
        mov     vpagen,al       ; store it
        push    ax              ; save page number
        mov     ah,5            ; bios call to change vpage
        int     10H             ; /
        pop     ax              ; get page back
        mov     bx,0b800H       ; base page address
        add     bh,al           ; set new base page seg
        mov     vpage,bx        ; /
        mov     al,vpagep       ; get previous page number
        mov     ah,160          ; convert to a screen address
        mul     ah              ;   /
        mov     bx,ax           ; /
        mov     es,vpage        ; get seg of current page
        or      byte ptr es:1[bx],8; highlight
        or      byte ptr es:3[bx],8; /
        ret                     ; exit
;--------------------------------------------------------------
; copy menus in all pages
;
menus:  mov     dx,0b800H       ; address of page0
        mov     di,offset dgroup:$menu ; point to the menu text
        mov     bp,[di]         ; get number of lines
        add     di,4            ; point to start of text
        mov     cx,_numpg       ; 8/4 pages to do
        inc     cx              ; /
menus1: push    cx              ; save outer count
        push    di              ; save orig index
        mov     cx,bp           ; get count of lines
        mov     es,dx           ; set target seg
        mov     bx,0            ; screen offset is 0
menus2: mov     ax,[di]         ; get character
        mov     es:[bx],ax      ; put it to the screen
        mov     ax,2[di]        ; get 2nd of three
        mov     es:2[bx],ax     ; put it away
        mov     ax,4[di]        ; get third
        mov     es:4[bx],ax     ; put it away
        add     di,6            ; bump indexes
        add     bx,160          ; next line for video
        loop    menus2          ; do all text lines
        mov     al,dh           ; get page #
        and     al,byte ptr _numpg; 0-7
        mov     ah,160          ; convert to line number
        mul     ah              ; /
        mov     bx,ax           ; now it's an address
        or      byte ptr es:5[bx],8; make it brite
        pop     di              ; get orig index back
        add     dh,1            ; bump to next page
        pop     cx              ; get page count
        loop    menus1          ; do all pages
        ret                     ; exit
;--------------------------------------------------------------
; display modules names
;
shoall: test    usesf,1         ; want to use screen file?
        jz      shoall0         ; no, then use internal data
        ;
        mov     ah,3dh          ; dos open file command
        mov     al,0            ; read only
        mov     dx,offset dgroup:_scrfn; point to file name
        int     21H             ; open the file
        jc      shoall0         ; internal data if no file
        ;
        push    ax              ; save file handle
        mov     bx,ax           ; set up file handle
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,vpage        ; set page seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4096         ; screen is 4K bytes
        int     21h             ; read the file
        pop     ds              ; restore data seg
        jc      errexit         ; bomb if error
        ;
        pop     bx              ; get file handle
        mov     ah,3eh          ; dos close file
        int     21h             ; close the file
        ret                     ; exit
        ;
errexit:pop     ax              ; discard return address        
        jmp     split1          ; exit
        ;
shoall0:cld                     ; direction forward
        mov     ax,0b800h       ; set up for block copy
        mov     es,ax           ;   /
        mov     si,offset dgroup:modscr
        mov     di,0            ; /
        mov     cx,2048         ;/
        rep     movsw           ; move from vartbl to screen
        ret                     ; exit
;==============================================================
; save modules
;
savmod: test    _tmpfn,-1       ; want to do it?
        jnz     savmodt         ; yes, branch
        ret                     ; no, just return
savmodt:mov     dx,offset dgroup:_tmpfn; point to file name
        call    savmods         ; save the stuff
        test    errflg,-1       ; was there an error
        jz      savmodu         ; no, go on
        mov     ax,offset dgroup:_noundo; yes, give parting shot
        mov     byemsg,ax       ; /
        jmp     split           ; exit
savmodu:ret
;--------------------------------------------------------------
; save modules & sequencers
; call with dx pointing to filename
;
savmods:mov     ah,3ch          ; dos create file command
        mov     cx,0            ; regular file
        int     21H             ; create the file
        call    erropw          ; check for disk error
        ;
        push    ax              ; save file handle
        mov     bx,ax           ; set up file handle
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:_header; point to header
        mov     cx,128          ; 128 byte header
        int     21h             ; save it
        mov     cx,128          ; 128 byte header
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,seg bufsp    ; set small seq seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4096         ; 16 seq's of 256 bytes each
        int     21h             ; save them
        pop     ds              ; restore data seg
        mov     cx,4096         ; 16 seq's of 256 bytes each
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,seg buffs    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,8000H        ; save half at a time
        int     21h             ; save first half
        pop     ds              ; restore data seg
        mov     cx,8000H        ; save half at a time
        call    errwrt          ; check for disk error
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,seg buffs    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,8000h        ; page offset for 2nd half
        mov     cx,8000H        ; save half at a time
        int     21h             ; save second half
        pop     ds              ; restore data seg
        mov     cx,8000H        ; save half at a time
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,seg bufpa    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,8000h        ; save half at a time
        int     21h             ; save first half
        pop     ds              ; restore data seg
        mov     cx,8000h        ; save half at a time
        call    errwrt          ; check for disk error
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,seg bufpa    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,8000h        ; page offset for 2nd half
        mov     cx,8000h        ; save half at a time
        int     21h             ; save second half
        pop     ds              ; restore data seg
        mov     cx,8000h        ; save half at a time
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,0bc00h       ; set page 4 seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4000H        ; 4 screens of 4K bytes
        int     21h             ; save the video screens
        pop     ds              ; restore data seg
        mov     cx,4000H        ; 4 screens of 4K bytes
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        push    ds              ; save data seg
        mov     dx,0b800h       ; set page 0 seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4000H        ; 4 screens of 4K bytes
        int     21h             ; save the video screens
        pop     ds              ; restore data seg
        mov     cx,4000H        ; 4 screens of 4K bytes
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:valsav; point to values
        mov     cx,valend-valsav; cx = bytes to save
        int     21h             ; save the values
        mov     cx,valend-valsav; cx = bytes to save
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:mvlsav; point to values
        mov     cx,mvlnum       ; cx = bytes to save
        int     21h             ; save the values
        mov     cx,mvlnum       ; cx = bytes to save
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:_modsrc; point to module source table
        mov     cx,offset dgroup:_chrtbl; calc number of bytes
        sub     cx,dx           ; cx = bytes in modsrc table
        push    cx
        int     21h             ; save the modsrc table
        pop     cx
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:_exetbl; module exec table
        mov     cx,2048         ; 512 modules @ 4 bytes each
        int     21h             ; save the table
        mov     cx,2048         ; 512 modules @ 4 bytes each
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:vartbl; variable table
        mov     cx,varsiz       ; var table
        int     21h             ; save the table
        mov     cx,varsiz       ; var table
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,40h          ; dos write file command
        mov     dx,offset dgroup:_modtxt; module text
        mov     cx,offset dgroup:?modtxt; end of module text
        sub     cx,dx           ; cx = bytes in module text
        push    cx
        int     21h             ; save the table
        pop     cx
        call    errwrt          ; check for disk error
        ;
        pop     bx              ; get file handle
        mov     ah,3eh          ; dos close file
        int     21h             ; close the file
        call    errclw          ; check for disk error
        ret                     ; exit
;--------------------------------------------------------------
; load modules from _tmpfn
;
lodmod: test    _tmpfn,-1       ; want to do it?
        jz      lodmodq         ; no, just return
        mov     ah,3dh          ; dos open file command
        mov     al,0            ; read only
        mov     dx,offset dgroup:_tmpfn; point to file name
        int     21H             ; open the file
        call    errundo         ; check for undo error
        mov     dl,_mpab        ; get current mpab status
        push    dx              ; save on stack
        or      _mpab,15        ; force all
        call    lodmod0         ; do the rest
        pop     dx              ; get mpab status
        mov     _mpab,dl        ; restore
lodmodq:ret                     ; exit
;--------------------------------------------------------------
; load modules with filename already setup (as lodmod, above)
;
lodmod0:
        push    ax              ; save file handle
        mov     bx,ax           ; set up file handle
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:_header; point to header
        mov     cx,128          ; 128 byte header
        int     21h             ; load it
        call    erropr          ; check for disk error
        ;
        cmp     _header,version; right version?
        jnz     lodmodz         ; no, exit
        cmp     _header+1,release; right release
        jz      lodmod1         ; yes, go on
lodmodz:test    _mpab,1         ; want to load MODS
        jz      lodmod1         ; no, then it's ok
        and     _mpab,0feh      ; zip the MOD bit
        call    dompab          ; show new mpab
        mov     dx,offset dgroup:_errver; else give message
        call    errmsg          ; /
        ;
lodmod1:test    _mpab,8         ; want to do this?
        jz      lodmod2         ; no, branch
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,seg bufsp    ; set small seq seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4096         ; 16 seq's of 256 bytes each
        push    cx              ; save number of read bytes
        int     21h             ; load them
        pop     cx              ; get number of read bytes
        pop     ds              ; restore data seg
        call    errqrd          ; check for disk error
        ;
lodmod2:test    _mpab,4         ; want to do this?
        jz      lodmod3         ; no, branch
        pop     bx              ; yes, set file pointer
        push    bx              ; handle
        mov     cx,0            ; ms word of pointer
        mov     dx,4096+128     ; ls word of pointer
        mov     al,0            ; offset from start of file
        mov     ah,42H          ; Move File Pointer
        int     21H             ; dos call
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,seg buffs    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,8000H        ; load half at a time
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        pop     ds              ; restore data seg
        call    errqrd          ; check for disk error
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,seg buffs    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,8000h        ; page offset for 2nd half
        mov     cx,8000H        ; load half at a time
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        pop     ds              ; restore data seg
        call    errqrd          ; check for disk error
        ;
lodmod3:test    _mpab,2         ; want to do this?
        jz      lodmod4         ; no, branch
        pop     bx              ; yes, set file pointer
        push    bx              ; handle
        mov     cx,1            ; ms word of pointer
        mov     dx,4096+128     ; ls word of pointer
        mov     al,0            ; offset from start of file
        mov     ah,42H          ; Move File Pointer
        int     21H             ; dos call
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,seg bufpa    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,8000h        ; load half at a time
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        pop     ds              ; restore data seg
        call    errqrd          ; check for disk error
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,seg bufpa    ; set large seq seg
        mov     ds,dx           ; /
        mov     dx,8000h        ; page offset for 2nd half
        mov     cx,8000h        ; load half at a time
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        pop     ds              ; restore data seg
        call    errqrd          ; check for disk error
        ;
lodmod4:test    _mpab,1         ; want to do this?
        jnz     lodmod5         ; yes, branch
        jmp     lodmodx         ; no, just go to exit
lodmod5:pop     bx              ; yes, set file pointer
        push    bx              ; handle
        mov     cx,2            ; ms word of pointer
        mov     dx,4096+128     ; ls word of pointer
        mov     al,0            ; offset from start of file
        mov     ah,42H          ; Move File Pointer
        int     21H             ; dos call
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,0bc00h       ; set page 4 seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4000H        ; 4 screens of 4K bytes
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        pop     ds              ; restore data seg
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        push    ds              ; save data seg
        mov     dx,0b800h       ; set page 0 seg
        mov     ds,dx           ; /
        mov     dx,0            ; page offset is 0
        mov     cx,4000H        ; 8 screens of 4K bytes
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        pop     ds              ; restore data seg
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:valsav; point to values
        mov     cx,valend-valsav; cx = bytes to load
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:mvlsav; point to values
        mov     cx,mvlnum       ; cx = bytes to load
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:_modsrc; point to module source table
        mov     cx,offset dgroup:_chrtbl; calc number of bytes
        sub     cx,dx           ; cx = bytes in modsrc table
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:_exetbl; module exec table
        mov     cx,2048         ; 512 modules @ 4 bytes each
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:vartbl; variable table
        mov     cx,varsiz       ; var table
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        call    errxrd          ; check for disk error
        ;
        pop     bx              ; get handle
        push    bx              ; save it again
        mov     ah,3fh          ; dos read file command
        mov     dx,offset dgroup:_modtxt; module text
        mov     cx,offset dgroup:?modtxt; end of module text
        sub     cx,dx           ; cx = bytes in module text
        push    cx              ; save read bytes
        int     21h             ; load first half
        pop     cx              ; restore read bytes
        call    errxrd          ; check for disk error
        ;
lodmodx:
        pop     bx              ; get file handle
        mov     ah,3eh          ; dos close file
        int     21h             ; close the file
        call    errclr          ; check for disk error
        ret                     ; exit
;--------------------------------------------------------------
; delete temp file
;
delmod: test    _tmpfn,-1       ; want to do it
        jz      delmodq         ; no, just exit
        mov     dx,offset dgroup:_tmpfn; delete the load file
        mov     ah,41h          ; dos delete function call
        int     21h             ; /
delmodq:ret
;==============================================================
; pointing device interface
;--------------------------------------------------------------
; The following pointing device interface assumes an interrupt
; driven microsoft-compatable mouse.  When a the mouse position
; changes, or a button is pushed, the interrupt routine sets
; the new x, y and flag, but does no other processing.
; The cursor update and other action is performed by the work
; loop, thus allowing multiple page usage, and control over when
; cursor updating should occur.
;--------------------------------------------------------------
; initialize pointing device
;
initpd: 
        mov     ax,0            ; test for mouse
        mov     es,ax           ; /
        mov     bx,0cch         ; es:bx = mouse inte vector
        cmp     es:[bx],ax      ; int vector = 0?
        jz      pdng            ; yes, exit
        mov     ax,es:2[bx]     ; no, get the vector addr
        mov     bx,es:[bx]      ; /
        mov     es,ax           ; es:bx = vector addr
        cmp     byte ptr es:[bx],0cfh; pointing to return?
        jnz     pdok            ; no, go to it 
pdng:
        mov     dx,offset nopd$ ; no mouse, print message
        call    print$          ; /
        jmp     split1          ; exit program
pdok:   mov     ax,0            ; initialize
        int     33H             ; mouse driver inte
        mov     ah,1            ; turn dos cursor off
        mov     ch,32           ;     /
        mov     cl,0            ;   /
        int     10H             ; /
        ret
nopd$   db      'No Pointing Device$',cr,lf
;--------------------------------------------------------------
; this routine is called only by interrupt, when
; the pd position or flag changes.
;
pdupd   proc    far             ; called by interrupt
        mov     di,seg dgroup    ; set local seg
        mov     ds,di           ; /
;        test    al,1EH          ; button change?
;        jz      pdupd1          ; no, branch
        test    al,14H          ; button released
        jz      pdupd2          ; no, branch
        or      bl,80H          ; set bit 7 hi
pdupd2: mov     al,pdf          ; or with prev bit 7
        and     al,80H          ;   /
        or      bl,al           ; /
        mov     pdf,bl          ; store flags
pdupd1: mov     ax,dx           ; convert pixel xy to char xy
        mov     bx,cx           ;       /
        mov     cl,3            ;     /
        shr     ax,cl           ;   /
        shr     bx,cl           ; /
        mov     pdx,bl          ; save in pdx, pdy
        mov     pdy,al          ; /
        ;
        vxyadr                  ; convert vx,vy to offst in bx
        mov     ax,curadr       ; get last cursor address
        mov     curadr,bx       ; save the new one
        mov     es,vpage        ; point to current video page
        test    curflg,1        ; wanna do the normal cursor
        jnz     pdupd3          ; no, branch
        xchg    bx,ax           ; get addr of old cursor
        mov     dx,curdata      ; get old cursor data
        mov     es:[bx],dx      ; restore
        xchg    bx,ax           ; get addr of new cursor
        mov     dx,es:[bx]      ; get new data
        mov     curdata,dx      ; save it
        mov     dh,curcol       ; get cursor color
        or      dh,dh           ; doing it?
        jz      pdupd3          ; no, branch
        mov     ch,pdf          ; yes, get flag info
        mov     cl,5            ; show it
        shl     ch,cl           ;   /
        or      dh,ch           ; /
pdupd4: mov     es:[bx],dx      ; display cursor
        ;
pdupd3: mov     cx,execur       ; get cursor exe address
        or      cx,cx           ; only do if nz
        jz      pdupdx          ;   /
        jmp     cx              ; /
pdupdx: ret                     ; exit
pdupd   endp

;--------------------------------------------------------------
; show cursor
;
        public  curon
curon   proc    near
        mov     es,vpage        ; point to current video page
        test    curflg,1        ; special cursor?
        jz      curon0          ; no, branch
        ;
        mov     di,modchar      ; get char table
        mov     cx,[di]         ; get number of lines
        add     di,4            ; point to 1st char
        mov     bx,curadr       ; cursor address
        dec     bx              ; shift for module
        dec     bx              ; /
        call    shomod$         ; show the module
        jmp     short curon2    ; branch around regular stuff
        ;
curon0: mov     bx,curadr       ; get last cursor address
        mov     dx,curdata      ; get cursor data
        test    curonf,1        ; want to restore?
        jz      curon1          ; no, branch
        mov     curonf,0        ; yes, clear flag
        mov     dx,es:[bx]      ; use screen character
        mov     curdata,dx      ; /
        ;
curon1: mov     dh,curcol       ; get cursor color
        or      dh,dh           ; doing it?
        jz      curon2          ; no, branch
        mov     ch,pdf          ; yes, get flag info
        mov     cl,5            ; show it
        shl     ch,cl           ;   /
        or      dh,ch           ; /
        mov     es:[bx],dx      ; display cursor
        ;
curon2: mov     cx,1fh          ; inte on any change
        mov     ax,12           ; "set call mask"
        mov     dx,cs           ; seg of pd update routine
        mov     es,dx           ; /
        mov     dx,offset pdupd ; address of pd update         
        int     33H             ; set the mask
        ret                     ; exit
curon   endp
;--------------------------------------------------------------
; hide cursor
; turn off pd interrupts
; must be called upon program exit
;
        public  curoff 
curoff  proc    near
        mov     es,vpage        ; point to current video page
        test    curflg,1        ; special cursor?
        jz      curoff0         ; no, branch
        ;
        mov     di,modchar      ; get char table
        mov     cx,[di]         ; get number of lines
        mov     bx,curadr       ; cursor address
        dec     bx              ; shift for module
        dec     bx              ; /
        call    fixmod$         ; restore the screen
        ;
        mov     bx,curadr       ; save cursor
        push    ds              ; save data seg
        mov     ax,seg buffv    ; get back buffer seg
        mov     ds,ax           ; /
        mov     ax,es:[bx]      ; get current screen info
        mov     [bx],ax         ; put it in back buffer
        pop     ds              ; get data seg back
        mov     curdata,ax      ; update cursor data
        jmp     short curoff1   ; jump around regular stuff
        ;
curoff0:mov     bx,curadr       ; get last cursor address
        mov     dx,curdata      ; get cursor data
        mov     es:[bx],dx      ; display cursor
        ;
curoff1:mov     cx,0            ; mask intes
        mov     ax,12           ; "set call mask"
        mov     dx,cs           ; seg of pd update routine
        mov     es,dx           ; /
        mov     dx,offset pdupd ; address of pd update         
        int     33H             ; set the mask
        ret                     ; exit
curoff  endp
;==============================================================
; video display routines
;--------------------------------------------------------------
; module cursor
; call with with ax= old curadr, bx:es=current curadr
; addr of character list is in modchar
;
modcur  proc far
        push    bx              ; save new curadr
        mov     bx,ax           ; get old curadr
        dec     bx              ; modules at vx-1
        dec     bx              ; /
        mov     di,modchar      ; point to module char source
        mov     cx,[di]         ; get the line count
        push    cx              ; save for later
        add     di,4            ; point to first char
        push    di              ; save for later
        call    fixmod$         ; restore the old stuff
        pop     di              ; it's later
        pop     cx              ; get count
        pop     bx              ; get new curadr
        push    bx              ; save it again
        dec     bx              ; modules at vx-1
        dec     bx              ; /
        call    shomod$         ; show the modules
        pop     bx              ; get new curadr
        or      byte ptr es:1[bx],18H ; cursor
        ret                     ; exit
modcur  endp
;--------------------------------------------------------------
; draw modules to screen
; call with:    di=module character array
;               cx=count of module char lines
;               es:bx=video page:offset of 1st char
;   
shomod$ proc    near
        push    bp              ; save bp
        mov     bp,ds           ; bp = data seg
        mov     dx,seg buffv    ; dx = back buffer seg
shomod1:mov     ax,[di]    ; get first char
        xchg    ax,es:[bx]      ; put it on the screen
        mov     ds,dx           ; set buffer seg
        mov     ds:[bx],ax      ; save the old one
        mov     ds,bp           ; restore data seg
        inc     di              ; point to next
        inc     di              ; /
        mov     ax,[di]         ; get 2nd character
        xchg    ax,es:2[bx]     ; put it on the screen
        mov     ds,dx           ; set buffer seg
        mov     ds:2[bx],ax     ; save the old one
        mov     ds,bp           ; restore data seg
        inc     di              ; point to next
        inc     di              ; /
        mov     ax,[di]         ; get 3rd char
        xchg    ax,es:4[bx]     ; put it on the screen
        mov     ds,dx           ; set buffer seg
        mov     ds:4[bx],ax     ; save the old one
        mov     ds,bp           ; restore data seg
        inc     di              ; point to next
        inc     di              ; /
        add     bx,160          ; next line
        loop    shomod1         ; do all of module
        pop     bp              ; restore bp
        ret
shomod$ endp
;--------------------------------------------------------------
; restore screen from modules previously drawn
; call with:    di=module character array
;               cx=count of module char lines
;               es:bx=video page:offset of 1st char
;   
fixmod$ proc    near
        push    ds              ; save data seg
        mov     ax,seg buffv    ; set ds to back buffer
        mov     ds,ax           ; /
fixmod1:mov     ax,ds:[bx]      ; get the old char
        mov     es:[bx],ax      ; put it back on the screen
        mov     ax,ds:2[bx]     ; get the old char
        mov     es:2[bx],ax     ; put it back on the screen
        mov     ax,ds:4[bx]     ; get the old char
        mov     es:4[bx],ax     ; put it back on the screen
        add     bx,160          ; next line
        loop    fixmod1         ; do all of module
        pop     ds              ; restore data seg
        ret
fixmod$ endp
;--------------------------------------------------------------
; erase module from screen
; call with es:bx = module tag addr
;           cx = count of char lines
;
eramod$ proc    near 
        mov     word ptr es:[bx],0  ; erase center char
        mov     word ptr es:2[bx],0 ; erase right char
        mov     word ptr es:-2[bx],0; erase left char
        add     bx,160          ; next line
        loop    eramod$         ; loop til done
        ret                     ; exit
eramod$ endp
;--------------------------------------------------------------
; fix blink bit for a blinking module
; call with es:bx = module tag addr
;           cx = count of char lines
;
unblink proc    near 
        and     byte ptr es:1[bx],07fh ; fix center char
        and     byte ptr es:3[bx],07fh ; fix right char
        and     byte ptr es:-1[bx],07fh; fix left char
        add     bx,160          ; next line
        loop    unblink         ; loop til done
        ret                     ; exit
unblink endp
;==============================================================
; get file name, if any, from command line
;
getfn   proc    near
        mov     es,_bases               ; es = base seg
        mov     di,80h                  ; di = offset of cmd line
        mov     si,offset dgroup:_savfn ; si = save file name buffer
        mov     cl,es:[di]              ; get the number of bytes
        cmp     cl,9                    ; 8 bytes maximum
        jbe     getfn3                  ;  /
        mov     cl,9                    ; /
getfn3: mov     ch,0                    ; /
        or      cl,cl                   ; exit if no name given
        jnz     getfna                  ; /
        clc                             ; cy clr means no name
        ret                             ; /
getfna: inc     di                      ; point to start of text
getfn0: mov     al,es:[di]              ; get first char
        cmp     al,' '                  ; ignore spaces
        jz      getfn1                  ; /
        cmp     al,'.'                  ; stop on dot or 0
        jz      getfn2                  ;   /
        cmp     al,0                    ;  /
        jz      getfn2                  ; /
        mov     [si],al                 ; put char in save file name buffer
        inc     si                      ; bump fn pointer
getfn1: inc     di                      ; bump cmd line pointer
        loop    getfn0                  ; loop to max of input chars
        ;
getfn2: mov     byte ptr [si],'.'       ; set up extension
        mov     byte ptr 1[si],'M'      ;    /
        mov     byte ptr 2[si],'B'      ;   /
        mov     byte ptr 3[si],' '      ;  /
        mov     byte ptr 4[si],0        ; /
        stc                             ; cy set means fn given
        ret                             ; exit
getfn   endp
;--------------------------------------------------------------
; show save file name on screen 0

showfn:
        mov     dx,0b800h               ; es = page 0
        mov     es,dx                   ; /
        mov     di,0a46h                ; di = char addr
        mov     si,offset dgroup:_savfn ; si = temp file name buffer
        mov     cx,8                    ; 8 chars to do
        mov     dl,0                    ; flag for end of name
showfn1:test    dl,1                    ; reached end of name?
        jnz     showfn2                 ; yes, branch
        mov     al,[si]                 ; get the char
        call    touc                    ; convert to upper case
        cmp     al,'.'                  ; end of name
        jnz     showfn3                 ; no, branch
        mov     dl,1                    ; yes, set flag
showfn2:mov     al,' '                  ; set char to blank
showfn3:mov     es:[di],al              ; write the char
        inc     di                      ; bump pointers
        inc     di                      ;  /
        inc     si                      ; /
        loop    showfn1                 ; do 8 chars
        ret
;==============================================================
; get a string from the keyboard to _inbuf
; call with first byte of _inbuf set to max chars
;
getkey:
        mov     ah,1            ; turn dos cursor on
        mov     ch,6            ;   /
        mov     cl,7            ;  /
        int     10H             ; /
        ;
        mov     dx,offset dgroup:_inbuf
        mov     ah,0ah          ; dos read buffer line function
        int     21h             ; /
        ;
        mov     ah,1            ; turn dos cursor off
        mov     ch,32           ;   /
        mov     cl,0            ;  /
        int     10H             ; /
        ;
        ret     
;==============================================================
; read directory into the filename area
;
getdir: call    clrdir          ; clear the directory area
        ;
        mov     dx,offset dgroup:_dirfn; now read the name
        mov     cx,0            ; attribute "normal"
        mov     ah,4eh          ; read first
        int     21h             ; dos call
        jc      getdirx         ; exit if no match
        call    dodir0          ; else print it
        ;
        mov     cx,30           ; 30+first+room max
getdir1:push    cx              ; save count
        mov     ah,4fh          ; read next
        int     21h             ; dos call
        pop     cx              ; get count
        jc      getdirx         ; exit if no match
        push    cx              ; save count
        call    dodir           ; else print it
        pop     cx              ; get count
        loop    getdir1         ; do until done or limit
getdirx:
        ;
        mov     ah,36h          ; get free disk space
        mov     dl,0            ; default drive
        int     21h             ; dos call
        mul     cx              ; find out in bytes
        mul     bx              ; result in dx:ax
        mov     ax,dx           ; /65K
        mov     cl,2            ; /4 = 256K/file
        shr     ax,cl           ; /
        push    ax              ; save result
        ;
        mov     ax,0b800h       ; set up video seg
        mov     es,ax           ; /
        mov     ax,diradr       ; current offset
        add     ax,0612h        ; ah=x
        mov     bl,ah           ; al=y, bl=x
        mov     bh,0            ; /
        vxyadr                  ; bx = video page address
        mov     colr,grey
        mov     word ptr es:[bx],gry+'['; set up brackets
        mov     word ptr es:8[bx],gry+']'
        add     bx,2
        ;
        pop     ax              ; get numb of files
        mov     room,al         ; save the room number
        mov     ah,0            ; 50 MB is enough
        call    toddec          ; print them
        ;
        ret                     ; split
;--------------------------------------------------------------
; read from _inbuf into the filename area
; do 4 names, then bump to next column
; call dodir0 to initialize, then call dodir
;
dodir0: mov     diradr,0        ; initialize address
dodir:  mov     ax,0b800h       ; set up video seg
        mov     es,ax           ; /
        mov     ax,diradr       ; current offset
        add     ax,0612h        ; ah=x
        mov     bl,ah           ; al=y, bl=x
        mov     bh,0            ; /
        vxyadr                  ; bx = video page address
        mov     di,9eh          ; point to source
        push    ds              ; save local data seg
        mov     ds,_bases       ; get system data seg
        mov     cx,8            ; 8 max to do
dodir1: mov     al,[di]         ; get the char
        cmp     al,'.'          ; extension ?
        jz      dodir2
        mov     es:[bx],al      ; no, write the char
        inc     bx              ; bump pointers
        inc     bx              ;  /
        inc     di              ; /
        loop    dodir1          ; loop
        ;
dodir2: pop     ds              ; get local ds back
        mov     ax,diradr       ; bump screen address
        inc     al              ; bump y
        test    al,4            ; 3 max
        jz      dodir3          ; branch if < 4
        mov     al,0            ; else reset y   
        add     ah,9            ; .. bump x
dodir3: mov     diradr,ax       ; put it away
        ret
;--------------------------------------------------------------
; clear the directory filename area
;
clrdir: mov     ax,0b800h       ; set up video seg
        mov     es,ax           ; /
        mov     di,0b4ch        ; point to 1st char
        mov     dl,4            ; 4 lines
        mov     ax,yel          ; set color
clrdir0:mov     bx,0            ; /
        mov     cx,72           ; 72 words per line
clrdir1:mov     es:[bx+di],ax   ; set the word
        inc     bx              ; bump
        inc     bx              ; /
        loop    clrdir1         ; do the line
        add     di,160          ; next line
        dec     dl              ;  /
        jnz     clrdir0         ; /
        ret
;==============================================================
; show the current path
;
dopath: mov     ah,19h          ; get current disk drive
        int     21h             ; dos call
        add     al,'A'          ; make it a letter
        mov     _inbuf,al       ; put it away
        mov     byte ptr _inbuf+1,':' ; send colon & slash
        mov     byte ptr _inbuf+2,'\' ; /
        ;
        mov     ah,47H          ; get current directory
        mov     dl,0            ; 0 = default drive
        mov     si,offset dgroup:_inbuf+3; put it in inbuf
        int     21h             ; dos call
        jc      dopathx         ; exit if error
        ;
        mov     ax,0b800h       ; set up video seg
        mov     es,ax           ; /
        mov     bx,58H+(16*160) ; offset for line
        mov     ax,yel          ; set color
        mov     cx,35           ; words in line
dopath1:mov     es:[bx],ax      ; set the word
        inc     bx              ; bump
        inc     bx              ; /
        loop    dopath1         ; do the line
        ;
        mov     bx,58H+(16*160) ; offset for line
        mov     di,offset dgroup:_inbuf; dir text
dopath2:mov     al,[di]         ; get the char
        or      al,al           ; end?
        jz      dopathx         ; yes, exit
        mov     es:[bx],al      ; no, output to screen
        inc     di              ; bump pointers
        inc     bx              ;  /
        inc     bx              ; /
        jmp     short dopath2   ; loop
dopathx:ret                     ; exit
;==============================================================
; critical error handeling (trapped DOS int 24H )
;
cerror: 
        push    bx              ; save cpu state
        push    cx              ;       /
        push    dx              ;      /
        push    di              ;     /
        push    si              ;    /
        push    bp              ;   /
        push    ds              ;  /
        push    es              ; /
        mov     al,0            ; setup to ignore
        test    ah,80h          ; disk error ?
        jnz     cerrorx         ; no, exit
        push    di              ; save error cond
        ;
        mov     dx,seg dgroup   ; set up data seg
        mov     ds,dx           ; /
        ;
        mov     dx,offset dgroup:_err_wp;write protect ermsg
        pop     ax              ; check for write protect
        or      al,al           ; write protect
        jz      cerror1         ; yes, branch
        mov     dx,offset dgroup:_err_dx; general ermsg
cerror1:call    errmsg          ; do the message
        ;
        mov     ah,al           ; put result in ah
        mov     al,0            ; ...to Ignore
        cmp     ah,'I'          ; wanna?
        jz      cerrorx         ; yes, go do it
        inc     al              ; ...to Retry
        cmp     ah,'R'          ;  /
        jz      cerrorx         ; /
        ;
        call    curoff          ; this is serious
        call    cls             ; clear screen
        mov     ah,2            ; set cursor to top of screen
        mov     dx,0            ;     /
        mov     bh,dh           ;   /
        int     10H             ; /
        mov     ah,1            ; turn dos cursor on
        mov     ch,6            ;     /
        mov     cl,7            ;   /
        int     10H             ; /
        call    stopt           ; stop system timer
        call    stopm           ; stop mpu ints
        mov     al,2            ; Quit
        ;
cerrorx:pop     es              ; restore cpu state
        pop     ds              ;       /
        pop     bp              ;      /
        pop     si              ;     /
        pop     di              ;    /
        pop     dx              ;   /
        pop     cx              ;  /
        pop     bx              ; /
        iret
;==============================================================
; Error message handler
; call with errormsg in dx
; returns with al = I, R, or Q
;
errmsg:
        push    dx              ; save message addr
        mov     vpagen,1        ; set page 1 as swap
        mov     al,0            ; set page 0 active
        call    page            ; /
        ;
        mov     ax,0b800h       ; set up video seg
        mov     es,ax           ; /
        mov     si,58H+(16*160) ; offset for line
        mov     di,offset dgroup:_foo; scratch buffer
        mov     bx,0            ; clear index
        mov     cx,35           ; words in line
errmsg0:
        mov     ax,es:[bx+si]   ; get the char
        mov     [bx+di],ax      ; save it
        inc     bx              ; bump
        inc     bx              ; /
        loop    errmsg0         ; do the line
        ;
        mov     ah,2            ; bios set cursor position
        mov     bh,0            ; page 0
        mov     dx,102CH        ; x,y of cursor
        int     10H             ; do bios int
        ;
        pop     dx              ; get the message
        mov     ah,9            ; print line
        int     21H             ; dos call
        ;
errmsg1:mov     ah,8            ; get a key response
        int     21h             ; dos call
        call    touc            ; convert to uppercase
        cmp     al,'I'          ; check for "I", "R", or "Q"
        jz      errmsg2         ; ...and branch if ok
        cmp     al,'E'          ;      /
        jz      errmsg2         ;     /
        cmp     al,'R'          ;    /
        jz      errmsg2         ;   /
        cmp     al,'Q'          ;  /
        jnz     errmsg1         ; /
errmsg2:push    ax              ; save result
        ;
        mov     ax,0b800h       ; set up video seg
        mov     es,ax           ; /
        mov     si,58H+(16*160) ; offset for line
        mov     di,offset dgroup:_foo; scratch buffer
        mov     bx,0            ; clear index
        mov     cx,35           ; words in line
        ;
errmsg3:
        mov     ax,[bx+di]      ; get the char
        mov     es:[bx+si],ax   ; restore it
        inc     bx              ; bump
        inc     bx              ; /
        loop    errmsg3         ; do the line
        ;
        mov     ah,2            ; bios set cursor position
        mov     bh,0            ; page 0
        mov     dx,102CH        ; x,y of cursor
        int     10H             ; do bios int
        ;
        pop     ax              ; return kbd input
        ret                     ; exit
;--------------------------------------------------------------
; errwrt: check for error while writing
; call with cx = proper file size
;
errwrt: jnc     errwrt1         ; branch if no error
        or      errflg,1        ; set flag
        mov     errwrd,ax       ; save message
        ret
errwrt1:cmp     ax,cx           ; correct size
        jz      errwrtx         ; yes, exit
        or      errflg,2        ; no, set flag
errwrtx:ret
;--------------------------------------------------------------
; check for error while opening write file
;
erropw: mov     errflg,0        ; clear error flag
        jnc     erropwx         ; exit if no error
        or      errflg,4        ; set flag
        mov     errwrd,ax       ; save message
erropwx:ret
;--------------------------------------------------------------
; check for error while closing write file
;
errclw: jnc     errclwx         ; exit if no error
        or      errflg,8        ; set flag
        mov     errwrd,ax       ; save message
errclwx:ret
;--------------------------------------------------------------
; check for error while opening read file
;
erropr: mov     errflg,0        ; clear error flag
        jnc     erroprx         ; exit if no error
        or      errflg,40H      ; set flag
        mov     errwrd,ax       ; save message
erroprx:ret
;--------------------------------------------------------------
; check for error while closing read file
;
errclr: jnc     errclrx         ; exit if no error
        or      errflg,80h      ; set flag
        mov     errwrd,ax       ; save message
errclrx:ret
;--------------------------------------------------------------
; errxrt: check for non fatal error while reading
; call with cx = proper file size
;
errqrd: jnc     errqrd1         ; exit if no error
        or      errflg,10h      ; set flag
        mov     errwrd,ax       ; save message
        ret
errqrd1:cmp     ax,cx           ; correct size
        jz      errqrdx         ; yes, exit
        or      errflg,20h      ; no, set flag
errqrdx:ret
;--------------------------------------------------------------
; errxrt: check for fatal error while reading
;
errxrd: jnc     errxrd1         ; exit if no error
errxrd0:mov     ax,offset dgroup:_errmod; yes, give parting shot
        mov     byemsg,ax       ; /
        jmp     split           ; exit
errxrd1:cmp     ax,cx           ; correct size 
        jnz     errxrd0         ; no, split
        ret
;--------------------------------------------------------------
; errundo: check for undo open error
; 
errundo:
        jnc     errundx         ; exit if no error
        mov     ax,offset dgroup:_opundo; yes, give parting shot
        mov     byemsg,ax       ; /
        jmp     split           ; exit
errundx:ret
;==============================================================
; debugging routines
        if      debug
;--------------------------------------------------------------
_DATA   SEGMENT
        public show0,show1,show2,show3,showq
show0   dw      0               ; debug show words
show1   dw      1               ;
show2   dw      2               ;
show3   dw      -1              ;
showq   dw      22 dup (0)
        dw      0

_DATA   ENDS
;--------------------------------------------------------------
; move 16 words, starting with ds:[bx] into show array
; all registers preserved
;
showw   proc    near
        push    es
        push    ds
        push    ax
        push    bx
        push    cx
        push    di
        mov     ax,seg dgroup
        mov     ds,ax
        mov     di,offset dgroup:showq
        mov     cx,44
showwl: mov     al,[bx]
        mov     [di],al
        inc     bx
        inc     di
        loop    showwl
showw2:
        pop     di
        pop     cx
        pop     bx
        pop     ax
        pop     ds
        pop     es
showw   endp
;--------------------------------------------------------------
; show 16 memory values starting with SHOW0
; all registers preserved
;
show    proc    near
        cmp     word ptr vpage,0b800h; don't show 0
        jnz     showa           ;     /
        ret                     ;    /
showa:  cmp     word ptr vpage,0bf00h; don't show 7
        jnz     showb           ;  /
        ret                     ; /
showb:  push    ax              ; preserve all registers
        push    bx              ;
        push    cx              ;
        push    dx              ;
        push    di              ;
        push    es              ;
        push    ds              ;
        mov     es,vpage        ; seg of screen
        mov     ax,seg dgroup    ; seg of SHO0
        mov     ds,ax           ; /
        mov     di,offset dgroup:show0 ; address of show0
        mov     bx,152          ; addr of 76,0
        mov     cx,25           ; 25 words
        mov     dh,yellow       ; color
showl:  mov     al,1[di]        ; get hi byte
        tohex                   ; convert it to hex
        mov     dl,ah           ; get hi nybble
        mov     es:[bx],dx      ; send hi nybble
        mov     dl,al           ; get low nybble
        mov     es:2[bx],dx     ; send low nybble
        mov     al,[di]         ; get low byte
        tohex                   ; convert it to hex
        mov     dl,ah           ; get hi nybble
        mov     es:4[bx],dx     ; send hi nybble
        mov     dl,al           ; get low nybble
        mov     es:6[bx],dx     ; send low nybble
        add     bx,160          ; move down
        add     di,2            ; bump index
        loop    showl           ; do 24 bytes
        pop     ds              ; restore registers
        pop     es
        pop     di
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret
show    endp
        endif   ; end of debug routines
;==============================================================
_TEXT   ENDS
;==============================================================
        end _doit       ; change to END if withc

