home *** CD-ROM | disk | FTP | other *** search
- ; WAS.ASM version 0.62
-
- comment &
-
- In the code that follows, when a reference is made to an absolute offset it
- means an offset to a byte relative to the zero location that is the first byte
- of the first EMS page allocated by WAS for the scroll back buffer. So the
- absolute offset of the first byte of the second EMS page is 16384, for the
- first byte of the third page 32768, etc. These offsets are stored in double
- word locations with the suffix -lo terminating the least significant word of
- the pointer and the suffix -hi terminating the most significant word of the
- pointer. The routine resolve converts these absolute offsets to pg:ofs form,
- where pg is the EMS page of the byte pointed to by the absolute offset and ofs
- is its offset within that page. The unresolve routine does the reverse and
- converts pg:ofs values back to absolute offsets. The suffixes -pg and -ofs
- are used to denote pg:ofs double word pointers.
-
- &
-
- ver equ "0.62" ; version number for copyright notice
- version equ "062" ; version number for summary message
- ofs equ offset ; abbreviations
- wp equ word ptr
- bpt equ byte ptr
- debug = 1 ; = 1 sets int 3, = 0 sets buzz
- cursizhi = 0ah ; index to high scan line of cursor
- cursizlo = 0bh ; index to low scan line of cursor
- speaker = 61h ; address of speaker port
- kbdhead = 1ah ; address of head pointer of kbd buffer
- kbdtail = 1ch ; address of tail pointer of kbd buffer
- cursorpos = 50h ; base address of ROM BIOS cursor pos
- linsiz = 160 ; size of screen line with attributes
- maxlines = 101 ; max number of screen lines supported
- minlines = 25 ; min number of screen lines supported
- k16 = 16384 ; 16k
- k32 = 32768 ; 32k
- lastcol = 79 ; last column of display
- pwr2div = 5 ; power of 2 divisor for interval proc
- alt = 8 ; Alt key bit in kbd status byte
- ltshift = 2 ; Left Shift bit in kbd status byte
- rtshift = 1 ; Right Shift bit in kbd status byte
- slock = 10h ; Scroll Lock bit in kbd status byte
- cr = 13 ; carriage return
- lf = 10 ; line feed
- no = 8f4eh ; 'N' with blinking bold attribute
- yes = 8f59h ; 'Y' with blinking bold attribute
- sumbg = 7 ; command summary background attribute
-
- biosdata segment at 40h ; useful ROM BIOS data locations
- org 17h
- kbdstat db ?
- org 49h
- videomode db ?
- org 4eh
- videofs dw ?
- org 63h
- crtport dw ?
- org 80h
- kbdstart dw ?
- kbdend dw ?
- org 84h
- numrows db ?
- org 85h
- charhigh dw ?
- biosdata ends
-
- jmps macro loc
- jmp short loc
- endm
-
- code segment
- assume cs:code
- org 2ch
- env dw ?
- org 100h
- entry: jmp start
- db 253 dup(0)
- thestack:
-
- countlo dw ?
- counthi dw ?
- dummy db 0
-
- interval proc near ; Routine to count interval between
- mov ax,countlo ; successive clicks of speaker for
- mov dx,counthi ; error buzz. The two count variables
- inc dx ; are initialized with a temporary
- dec_count: cmp dummy,1 ; int 8 routine at initialization time.
- je dec_count
- dec ax
- jnz dec_count
- dec dx
- jnz dec_count
- ret
- interval endp
-
- buzz proc near ; Causes the speaker to buzz by turning
- push ax ; it on and off to produce a tone with
- push cx ; a frequency dependent upon the size
- push dx ; of the pause due to the call to proc
- mov cx,50 ; interval. The duration of the call
- nextclick: in al,speaker ; to interval is independent of CPU
- jmp $+2
- xor al,2 ; speed.
- out speaker,al
- jmp $+2
- call interval
- loop nextclick
- pop dx
- pop cx
- pop ax
- ret
- buzz endp
-
- ; The lastpage variable is used to bypass calls to the EMM for logical pages
- ; that have already been mapped to physical page 0 (the most frequently mapped
- ; physical page).
-
- lastpage dw ?
- handle dw ? ; handle returned by the EMM
-
- ems proc near ; Implements call to the expanded
- cmp ax,4400h ; memory manager.
- jne doems
- cmp bx,lastpage
- mov lastpage,bx
- jne doems
- ret
- doems: push dx
- push bx
- push ax
- mov dx,handle
- int 67h
- or ah,ah
- jz emsout
-
- if debug ; If a resident debugger is installed
- mov dx,ax ; (e.g., Periscope) the debug constant
- pop ax ; can be set to 1 and this code will
- mov al,dh ; be executed if an EMS error occurs.
- pop bx ; The function causing the error is
- pop dx ; retained in ah while the error code
- int 3 ; is shown in al. Both bx and dx
- ret ; remain unchanged.
- else
- call buzz ; Otherwise you get a buzz.
- endif
-
- emsout: pop ax
- pop bx
- pop dx
- ret
- ems endp
-
- regen dw ?
- pfseg dw ?
-
- scr2ems proc near ; destroys cx and es
- push ds ; Copies screen (video regen buffer)
- mov ds,regen ; memory to EMS memory.
- mov es,pfseg
- rep movsw
- pop ds
- ret
- scr2ems endp
-
- ems2scr proc near ; destroys cx and es
- push ds ; Copies EMS memory to screen (video
- mov ds,pfseg ; regen buffer) memory.
- mov es,regen
- rep movsw
- pop ds
- ret
- ems2scr endp
-
- savcntx proc near ; destroys ax
- mov ah,47h ; save ems context
- call ems
- mov lastpage,-1 ; Setting lastpage to 0ffffh assures
- ret ; that the first mapping request will
- savcntx endp ; go through.
-
- rstcntx proc near ; destroys ax
- mov ah,48h ; restore ems context
- call ems
- ret
- rstcntx endp
-
- ; These variables are set by calls to the setvideo procedure.
-
- scrnsiz dw ? ; number of bytes in video regen buffer
- numlines dw ? ; number of lines on screen
- pointsize db ? ; size of character height
-
- ; It has been found better to address the hardware when turning the cursor on
- ; and off since this eliminates the necessity for use of ROM BIOS functions for
- ; cursor control. Calling int 10h routines at the arbitrary code locations at
- ; which WAS can halt the machine can result in system crashes at least for some
- ; types of BIOS ROMs.
-
- assume ds:biosdata
-
- curon proc near ; destroys ax, bx, dx and ds
- mov dx,crtport ; address CRT controller port
- mov bl,pointsize ; restored cursor size depends on
- mov bh,bl ; character height
- sub bl,2 ; devote 3 scan lines to cursor
- sub bh,4
- cmp pointsize,8
- jne setcur
- inc bl ; special provision for 8 x 8 character
- inc bh ; box
- setcur: mov al,cursizhi
- cli
- out dx,al
- jmp $+2 ; pause for I/O catch up
- inc dx
- mov al,bh
- out dx,al
- jmp $+2
- dec dx
- mov al,cursizlo
- out dx,al
- jmp $+2
- inc dx
- mov al,bl
- out dx,al
- jmp $+2
- sti
- ret
- curon endp
-
- curoff proc near ; destroys ax, bx, dx and ds
- mov dx,crtport
- mov al,cursizhi
- cli
- out dx,al
- jmp $+2
- inc dx
- mov al,31
- out dx,al
- jmp $+2
- dec dx
- mov al,cursizlo
- out dx,al
- jmp $+2
- inc dx
- sub al,al
- out dx,al
- jmp $+2
- sti
- ret
- curoff endp
-
- lastpg dw ? ; Stores page number of highest page.
- lastofs dw ? ; This is offset of byte just beyond
- ; the last location in the scroll
- ; buffer. This combination of lastpg:
- ; lastofs is the result of applying the
- ; resolve routine on the absolute
- ; pointer stored in endofslo:endofshi.
-
- scrsavsiz dw 60 * 160 + 1 ; size of buffer to save current screen
- scrsavofs dw 16384 - 60*160+1; offset of current screen save buf
-
- assume ds:code
-
- savscr proc near ; save current screen to EMS memory
- call savcntx
- mov ax,4400h ; access page to store screen
- mov bx,lastpg ; screen is stored at end of last EMS
- call ems ; page
- sub si,si
- mov di,scrsavofs ; location determined by 'l' switch
- mov cx,scrnsiz ; setvideo sets scrnsiz
- shr cx,1
- call scr2ems ; store current screen
- ret
- savscr endp
-
- rstscr proc near ; restore current screen from EMS
- mov ax,4400h ; access page of stored screen
- mov bx,lastpg
- call ems
- mov si,scrsavofs
- sub di,di
- mov cx,scrnsiz
- shr cx,1
- call ems2scr ; restore current screen
- call rstcntx ; restore EMS context before leaving
- ret
- rstscr endp
-
- headlo dw 0 ; Scroll back buffer is implemented as
- headhi dw 0 ; circular buffer with a head and tail
- taillo dw 0 ; pointer. The values are stored here
- tailhi dw 0 ; as absolute offsets that are resolved
- toplo dw ? ; into page and offset by resolve proc.
- tophi dw ? ; The top pointer points to the line
- ; saved in EMS that is currently shown
- ; at the top of the screen.
-
- settop proc near ; destroys ax
- mov ax,taillo ; Routine sets the top pointer from
- mov toplo,ax ; the tail pointer.
- mov ax,tailhi
- mov tophi,ax
- ret
- settop endp
-
- resolve proc near ; Converts absolute offsets within the
- push ax ; EMS scroll back buffer into page, and
- rcl ax,1 ; offset within page of corresponding
- rcl dx,1 ; EMS page.
- rcl ax,1
- rcl dx,1
- pop ax
- and ax,3fffh
- ret
- resolve endp
-
- unresolve proc near ; Converts EMS page and page offsets
- push bx ; back into absolute offsets within the
- sub bx,bx ; EMS scroll back buffer.
- rcr dx,1
- rcr bx,1
- rcr dx,1
- rcr bx,1
- or ax,bx
- pop bx
- ret
- unresolve endp
-
- frmbuf proc near ; Sets up appropriate EMS scroll back
- jcxz fbout ; buffer pages into physical pages 0
- call resolve ; and 1, then copies the number of
- mov si,ax ; bytes in cx to video memory.
- mov ax,4400h
- mov bx,dx
- call ems
- mov bx,k16
- sub bx,cx
- cmp si,bx
- jbe fbshow
- inc dx
- mov ax,4401h
- mov bx,dx
- call ems
- fbshow: shr cx,1
- call ems2scr
- fbout: ret
- frmbuf endp
-
- siz2cx proc near ; number of bytes in bx lines to cx
- mov ax,linsiz
- mul bx
- mov cx,ax
- ret
- siz2cx endp
-
- frmsav proc near ; lines from saved screen to video mem
- mov ax,4400h ; access page of stored screen
- mov bx,lastpg
- call ems
- mov si,scrsavofs
- shr cx,1
- call ems2scr
- ret
- frmsav endp
-
- endofslo dw ? ; This is an absolute offset to the byte
- endofshi dw ? ; just beyond the last location in the
- ; EMS scroll buffer.
-
- showattop proc near ; Display a full screen of lines from
- mov cx,numlines ; scroll back buffer and/or saved
- mov bp,cx ; current screen.
- sub bx,bx ; dx:ax contain top pointer at entry
- sub di,di
- push ax
- push dx
- sat1: cmp dx,tailhi
- jne satcmpend
- cmp ax,taillo
- je sattail1
- satcmpend: cmp dx,endofshi
- jne nextline
- cmp ax,endofslo
- je satwrap
- nextline: add ax,linsiz
- adc dx,0
- inc bx
- loop sat1
- mov cx,scrnsiz
- pop dx
- pop ax
- call frmbuf
- ret
- sattail1: call siz2cx
- pop dx
- pop ax
- mov bx,scrnsiz
- sub bx,cx
- push bx
- call frmbuf
- pop cx
- call frmsav
- ret
- satwrap: sub bp,bx
- call siz2cx
- pop dx
- pop ax
- call frmbuf
- sub ax,ax
- sub dx,dx
- mov cx,bp
- sub bx,bx
- sat2: cmp dx,tailhi
- jne satbumptr
- cmp ax,taillo
- je sattail2
- satbumptr: add ax,linsiz
- adc dx,0
- inc bx
- loop sat2
- call siz2cx
- sub ax,ax
- sub dx,dx
- call frmbuf
- ret
- sattail2: or bx,bx
- jz satdosav
- sub bp,bx
- call siz2cx
- sub ax,ax
- sub dx,dx
- call frmbuf
- satdosav: mov bx,bp
- call siz2cx
- call frmsav
- ret
- showattop endp
-
- margin dw 0 ; left column of marked area
- lnwdth dw 80 ; number of characters in a marked line
- monochrome db 0 ; marking is different for monochrome
-
- markline proc near ; Marks or unmarks a line of text.
- push ds ; A "line" can be one character wide.
- mov cx,lnwdth ; Such is the case when borders are
- push si ; moved one character column left or
- push di ; right.
- add si,margin
- add di,margin
- mov es,pfseg
- mov ds,pfseg
- markchar: lodsw
- cmp cs:monochrome,1 ; Attributes are set to reverse video
- jne color ; (70h) attribute or plain (07h) for
- cmp ah,70h ; monochrome monitors. This is the
- mov ah,7 ; only way to insure reverse video
- je stochr ; marking of lines, since ANSI.SYS (or
- mov ah,70h ; other like console drivers) can alter
- jmps stochr ; attributes in ways that prevent
- color: xor ah,77h ; marking to be visible if the xoring
- stochr: stosw ; that works so well for color were
- loop markchar ; also used for monochrome.
- pop di
- pop si
- add si,linsiz
- add di,linsiz
- pop ds
- ret
- markline endp
-
- markalin proc near ; Sets up the EMS pages for the marking
- mov ax,4400h ; carried out by markline proc.
- mov bx,dx
- call ems
- mov ax,si
- add ax,linsiz
- cmp ax,k16
- jbe mrklin
- mov ax,4401h
- inc dx
- mov bx,dx
- call ems
- mrklin: call markline
- ret
- markalin endp
-
- backandmark proc near ; This routine backs up linsiz bytes
- cmp dx,lastpg ; within the EMS scroll back buffer
- jne bambackup ; and marks a line. Used to move a
- cmp ax,scrsavofs ; marked line (or set of lines) up in
- jne bambackup ; the scroll back buffer.
- bamatend: mov ax,taillo
- mov dx,tailhi
- call resolve
- bambackup: mov bx,ax
- or bx,dx
- jnz bambackit
- mov ax,lastofs
- mov dx,lastpg
- bambackit: sub ax,linsiz
- jns bammarkit
- add ax,k16
- dec dx
- bammarkit: mov si,ax
- mov di,ax
- push ax
- push dx
- call markalin
- pop dx
- pop ax
- bamout: ret
- backandmark endp
-
- mark1ofs dw 0 ; Mark1 points to the first highlighted
- mark1pg dw 0 ; line in any series. Mark2 points to
- mark2ofs dw 0 ; the next location after the last
- mark2pg dw 0 ; highlighted line.
-
- linup proc near ; Displays one more line from the scroll
- push ds ; back buffer on the top line of the
- mov ax,40h ; screen, unless a shift key is pressed,
- mov ds,ax ; then a marked area within the scroll
- ; buffer will be moved up one line
- assume ds:biosdata
-
- test kbdstat,ltshift or rtshift
- pop ds
-
- assume ds:code
-
- jnz movhlup?
- mov ax,toplo
- mov dx,tophi
- cmp dx,headhi
- jne canlu
- cmp ax,headlo
- jne canlu
- ret
- canlu: sub ax,linsiz
- sbb dx,0
- jns lustotop
- add ax,endofslo
- adc dx,endofshi
- lustotop: mov toplo,ax
- mov tophi,dx
- call showattop
- ret
- movhlup?: mov ax,mark1ofs
- mov dx,mark1pg
- cmp dx,mark2pg
- jne athead?
- cmp ax,mark2ofs
- jne athead?
- ret
- athead?: mov bx,ax
- mov cx,dx
- mov ax,headlo
- mov dx,headhi
- cmp dx,tailhi
- jne maybehead
- cmp ax,taillo
- jne maybehead
- jmps topoflast?
- maybehead: call resolve
- cmp dx,cx
- jne movhlup
- cmp ax,bx
- jne movhlup
- ret
- topoflast?: cmp cx,lastpg
- jne movhlup
- cmp bx,scrsavofs
- jne movhlup
- ret
- movhlup: mov ax,bx
- mov dx,cx
- call backandmark
- stomark1: mov mark1ofs,ax
- mov mark1pg,dx
- mov ax,mark2ofs
- mov dx,mark2pg
- call backandmark
- mov mark2ofs,ax
- mov mark2pg,dx
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- linup endp
-
- mabmark proc near ; Mark-And-Bump Mark. Routine sets up
- mov si,ax ; and does the line marking without
- mov di,ax ; disturbing dx:ax line pointer.
- push ax
- push dx
- call markalin
- pop dx
- pop ax
- ret
- mabmark endp
-
- bumpdxax proc near ; Whenever there's a need in the code
- add ax,linsiz ; below to move the dx:ax pointer (with
- cmp ax,k16 ; a pg:ofs value) to the next scroll
- jb lastpg? ; buffer/current screen line, this
- sub ax,k16 ; routine is called.
- inc dx
- lastpg?: cmp dx,lastpg
- jne bdaout
- cmp ax,lastofs
- jne bdaout
- sub ax,ax
- sub dx,dx
- bdaout: ret
- bumpdxax endp
-
- markandbump proc near ; When routine is entered dx:ax points
- mov bx,ax ; to mark2. The proc marks EMS scroll
- mov cx,dx ; buffer at mark2, then bumps dx:ax
- mov ax,taillo ; before returning.
- mov dx,tailhi
- call resolve
- xchg ax,bx
- xchg dx,cx
- cmp dx,cx
- jne mabbump
- cmp ax,bx
- jne mabbump
- mov ax,scrsavofs
- mov dx,lastpg
- call mabmark
- add ax,linsiz
- ret
- mabbump: call mabmark
- call bumpdxax
- ret
- markandbump endp
-
- lastsavofs dw ? ; Actually the offset of the first byte
- ; beyond the last location for saving
- ; the current screen. Set by the
- ; setvideo procedure.
-
- lindn proc near ; Scrolls screen up by one line and
- push ds ; places a line from the EMS scroll
- mov ax,40h ; buffer or the current screen on the
- mov ds,ax ; bottom line of the screen. If either
- ; shift key is pressed it moves any
- assume ds:biosdata ; marked region down a line.
-
- test kbdstat,ltshift or rtshift
- pop ds
-
- assume ds:code
-
- jnz movhldn?
- mov ax,toplo
- mov dx,tophi
- cmp dx,tailhi
- jne canld
- cmp ax,taillo
- jne canld
- ret
- canld: add ax,linsiz
- adc dx,0
- cmp dx,endofshi
- jne ldstotop
- cmp ax,endofslo
- jne ldstotop
- sub ax,ax
- sub dx,dx
- ldstotop: mov toplo,ax
- mov tophi,dx
- call showattop
- ret
- movhldn?: mov ax,mark2ofs
- mov dx,mark2pg
- cmp dx,lastpg
- jne movhldn
- cmp ax,lastsavofs ; Here's the reason that 1 is
- jne movhldn ; added to 60 * 160 for the
- ret ; size of screen saving area.
- movhldn: call markandbump
- mov mark2ofs,ax
- mov mark2pg,dx
- mov ax,mark1ofs
- mov dx,mark1pg
- call markandbump
- mov mark1ofs,ax
- mov mark1pg,dx
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- lindn endp
-
- scrup proc near ; implements the PgUp key command
- mov ax,toplo
- mov dx,tophi
- cmp dx,headhi
- jne cansu
- cmp ax,headlo
- jne cansu
- ret
- cansu: mov cx,numlines
- sublinsiz: sub ax,linsiz
- sbb dx,0
- jns cmphead
- mov ax,endofslo
- mov dx,endofshi
- jmps sublinsiz
- cmphead: cmp dx,headhi
- jne subnext
- cmp ax,headlo
- je rtout
- subnext: loop sublinsiz
- rtout: mov toplo,ax
- mov tophi,dx
- call showattop
- ret
- scrup endp
-
- scrdn proc near ; implements the PgDn key command
- mov ax,toplo
- mov dx,tophi
- cmp dx,tailhi
- jne cansd
- cmp ax,taillo
- jne cansd
- ret
- cansd: mov cx,numlines
- addlinsiz: add ax,linsiz
- adc dx,0
- cmp dx,endofshi
- jne comptail
- cmp ax,endofslo
- jne comptail
- sub ax,ax
- sub dx,dx
- comptail: cmp dx,tailhi
- jne addnext
- cmp ax,taillo
- je atout
- addnext: loop addlinsiz
- atout: mov toplo,ax
- mov tophi,dx
- call showattop
- ret
- scrdn endp
-
- hmscr proc near ; implements the Home key command
- mov ax,headlo
- mov dx,headhi
- mov toplo,ax
- mov tophi,dx
- call showattop
- ret
- hmscr endp
-
- enscr proc near ; implements the End key command
- mov ax,taillo
- mov dx,tailhi
- mov toplo,ax
- mov tophi,dx
- call showattop
- ret
- enscr endp
-
- insrt proc near ; implements the Insert key command
- mov ax,toplo
- mov dx,tophi
- cmp dx,tailhi
- jne insout
- cmp ax,taillo
- je canins
- insout: ret
- canins: call rstcntx ; Must restore EMS context now since
- mov ax,600h ; the sav2ems routine does a savcntx/
- sub cx,cx ; rstcntx method.
- mov dx,numlines
- dec dx
- mov dh,dl
- mov dl,lastcol
- call sav2ems
- call savcntx
- call settop
- ret
- insrt endp
-
- cmp2tail proc near ; Is the dx:ax pointer equal to the
- cmp dx,tailhi ; tail pointer? Zero flag set iff so.
- jne c2tout
- cmp ax,taillo
- c2tout: ret
- cmp2tail endp
-
- firstmark proc near ; This routine does all the initiation
- mov cx,numlines ; of pointers to mark the first screen
- shr cx,1 ; line in any series and marks that
- mov ax,toplo ; first line.
- mov dx,tophi
- chkcrntscr: call cmp2tail ; If the dx:ax pointer is equal to the
- je incrntscr ; tail pointer, then we are viewing the
- add ax,linsiz ; current screen.
- adc dx,0
- cmp dx,endofshi
- jne tochkcrnt
- cmp ax,endofslo
- jne tochkcrnt
- sub ax,ax
- sub dx,dx
- tochkcrnt: loop chkcrntscr
- call cmp2tail
- je incrntscr
- jmps inscrlbak ; if not, we're going to mark a line
- incrntscr: mov ax,linsiz ; in the scroll buffer.
- mul cx
- add ax,scrsavofs
- mov dx,lastpg
- jmps lodmrkpg
- inscrlbak: call resolve
- lodmrkpg: mov si,ax
- mov di,ax
- mov mark1ofs,ax
- mov mark1pg,dx
- mov bx,dx
- add ax,linsiz
- cmp ax,k16
- jb stomark2
- sub ax,k16
- inc dx
- stomark2: mov mark2ofs,ax
- mov mark2pg,dx
- mov dx,bx
- call markalin
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- firstmark endp
-
- ; When a marked area is set in a region of the scroll buffer and the user moves
- ; the displayed region closer to the current screen so that the marks are out
- ; of sight and above the lines currently displayed, pressing the keypad plus
- ; will cause all lines in the scroll buffer from the end of the marked region
- ; to the top line of the present display to be marked. Mark2top is the routine
- ; that does that. In several places of the code for WAS the algorithm used
- ; to trace the chain of locations in the circular scroll buffer is to move one
- ; line at a time through the buffer. When a pointer reaches the end of the
- ; scroll buffer it is wrapped back to the beginning (location 0). This method
- ; while much more time consuming than a method that did pointer arithmetic and
- ; comparisons is lean on code size and very much easier to debug.
-
- mark2top proc near
- push ax
- push dx
- cmp dx,lastpg
- jne lodtop
- cmp ax,scrsavofs
- jb lodtop
- m2tout: pop dx
- pop ax
- ret
- lodtop: mov bp,tophi
- mov bx,toplo
- call unresolve
- mov si,ax ; Di:si will be the running pointer
- mov di,dx ; to count the lines to mark.
- sub cx,cx ; Initialize count.
- mov dx,tailhi
- mov ax,taillo
- topnow?: cmp di,bp
- jne tailnow?
- cmp si,bx
- jne tailnow?
- jcxz m2tout
- pop dx
- pop ax
- marknxt: mov si,ax
- mov di,ax
- push ax
- push dx
- push cx
- call markalin
- pop cx
- pop dx
- pop ax
- call bumpdxax
- loop marknxt
- ret
- tailnow?: cmp di,dx
- jne ptrandcnt
- cmp si,ax
- jne ptrandcnt
- pop dx
- pop ax
- ret
- ptrandcnt: add si,linsiz
- adc di,0
- cmp di,endofshi
- jne bumpcnt
- cmp si,endofslo
- jne bumpcnt
- sub si,si
- sub di,di
- bumpcnt: inc cx
- jmps topnow?
- mark2top endp
-
- setmk proc near ; The routine that sets a marked line
- mov ax,mark1ofs ; when the keypad plus key is pressed.
- mov dx,mark1pg
- cmp dx,mark2pg
- jne notfirst
- cmp ax,mark2ofs
- jne notfirst
- call firstmark
- ret
- notfirst: mov ax,mark2ofs
- mov dx,mark2pg
- cmp dx,lastpg
- jne maybemark
- cmp ax,lastsavofs
- jne maybemark
- ret
- maybemark: call mark2top
- push ax
- push dx
- mov ax,taillo
- mov dx,tailhi
- call resolve
- mov bx,ax
- mov cx,dx
- pop dx
- pop ax
- cmp dx,cx
- jne setupmark
- cmp ax,bx
- jne setupmark
- mov ax,scrsavofs
- mov dx,lastpg
- setupmark: mov si,ax
- mov di,ax
- push ax
- push dx
- call markalin
- pop dx
- pop ax
- call bumpdxax
- mov mark2ofs,ax
- mov mark2pg,dx
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- setmk endp
-
- rstmk proc near ; This routine resets a marked line
- mov ax,mark2ofs ; when the keypad minus key is pressed.
- mov dx,mark2pg
- cmp dx,mark1pg
- jne resetmark
- cmp ax,mark1ofs
- jne resetmark
- ret
- resetmark: sub ax,linsiz
- jns chklastpage
- add ax,k16
- dec dx
- jns rmmark
- mov ax,lastofs
- sub ax,linsiz
- mov dx,lastpg
- jmps rmmark
- chklastpage: cmp dx,lastpg
- jne rmmark
- mov bx,scrsavofs
- sub bx,linsiz
- cmp ax,bx
- jne rmmark
- mov ax,taillo
- mov dx,tailhi
- call resolve
- jmps resetmark
- rmmark: mov mark2ofs,ax
- mov mark2pg,dx
- mov si,ax
- mov di,ax
- call markalin
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- rstmk endp
-
- stuff? db ?
- keysleft db ?
- crflag db ?
- stuff1ofs dw ?
- stuff1pg dw ?
- stuff2ofs dw ?
- stuff2pg dw ?
-
- setstuff proc near ; This one is called when lines are
- mov stuff?,1 ; marked and WAS is leaving the hold
- mov keysleft,0 ; state. It initializes variables used
- mov crflag,0 ; in the operation to feed the keyboard
- mov stuff1ofs,ax ; buffer with the marked text.
- mov stuff1pg,dx
- mov stuff2ofs,bx
- mov stuff2pg,cx
- ret
- setstuff endp
-
- markarea proc near ; Marks (or unmarkes) the area from
- mamark: push ax ; mark 1 to mark2. This routine is
- push bx ; called to mark (unmark) borders of
- push cx ; the marked region or unmark all marked
- push dx ; text before WAS leaves the hold state.
- push si
- push di
- mov si,ax
- mov di,ax
- call markalin
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- call bumpdxax
- cmp dx,cx
- jne maattail?
- cmp ax,bx
- jne maattail?
- ret
- maattail?: cmp dx,di
- jne mamark
- cmp ax,si
- jne mamark
- mov ax,scrsavofs
- mov dx,lastpg
- jmps mamark
- markarea endp
-
- markdata proc near ; This sets up registers to point to
- mov ax,taillo ; the locations necessary prior to a
- mov dx,tailhi ; call to markarea.
- call resolve
- mov si,ax
- mov di,dx
- mov ax,mark1ofs
- mov dx,mark1pg
- mov bx,mark2ofs
- mov cx,mark2pg
- cmp dx,cx
- jne mdout
- cmp ax,bx
- mdout: ret
- markdata endp
-
- chkstat proc near ; Routine sets the zero flag based upon
- push ds ; the setting of bits in the keyboard
- mov bx,40h ; status byte common to the al register.
- mov ds,bx
-
- assume ds:biosdata
-
- and al,kbdstat
- pop ds
-
- assume ds:code
-
- ret
- chkstat endp
-
- ltshift? proc near ; Sets zero flag based upon status of
- mov al,ltshift ; the left shift key state.
- call chkstat
- ret
- ltshift? endp
-
- rtshift? proc near ; Sets zero flag based upon status of
- mov al,rtshift ; the right shift key state.
- call chkstat
- ret
- rtshift? endp
-
- markborder proc near ; Marks/unmarks marked area borders
- call markdata ; determined by the parameters of
- call markarea ; lnwdth and margin placed upon the
- pop ax ; stack by the calling routine.
- pop lnwdth
- pop margin
- push ax
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- markborder endp
-
- movlt proc near ; moves the border of a marked area to
- mov ax,mark1ofs ; the left
- mov dx,mark1pg
- cmp ax,mark2ofs
- jne doleft
- cmp dx,mark2pg
- jne doleft
- ret
- doleft: call ltshift?
- jnz lt_at_lt
- call rtshift?
- jnz lt_at_rt
- ret
- lt_at_lt: cmp margin,0
- jne lt_fm_lt
- ret
- lt_fm_lt: sub margin,2
- inc lnwdth
- push margin
- push lnwdth
- mov lnwdth,1
- call markborder
- ret
- lt_at_rt: cmp lnwdth,1
- jne lt_fm_rt
- ret
- lt_fm_rt: dec lnwdth
- push margin
- push lnwdth
- mov ax,lnwdth
- add margin,ax
- add margin,ax
- mov lnwdth,1
- call markborder
- ret
- movlt endp
-
- movrt proc near ; moves the border of a marked area to
- mov ax,mark1ofs ; the right
- mov dx,mark1pg
- cmp ax,mark2ofs
- jne doright
- cmp dx,mark2pg
- jne doright
- ret
- doright: call ltshift?
- jnz rt_at_lt
- call rtshift?
- jnz rt_at_rt
- ret
- rt_at_lt: cmp lnwdth,1
- jne rt_fm_lt
- ret
- rt_fm_lt: dec lnwdth
- add margin,2
- push margin
- push lnwdth
- sub margin,2
- mov lnwdth,1
- call markborder
- ret
- rt_at_rt: mov ax,lnwdth
- add ax,ax
- add ax,margin
- cmp ax,linsiz
- jne rt_fm_rt
- ret
- rt_fm_rt: inc lnwdth
- push margin
- push lnwdth
- mov ax,lnwdth
- dec ax
- add margin,ax
- add margin,ax
- mov lnwdth,1
- call markborder
- ret
- movrt endp
-
- saving db 1
-
- setsv proc near ; Toggles scroll buffer saving. Called
- xor saving,1 ; when the delete key is pressed.
- ret
- setsv endp
-
- ; The following routines prior to delmk support that procedure which is the one
- ; which is called when the delete key is pressed. The pg0 referred to below is
- ; the page that at any given time contains the source of the bytes to move to
- ; the destination page, pg1. Bytes are moved from pg0 to pg1. Each pg? cycles
- ; through those necessary to copy all lines below the marked area to the
- ; location that starts the marked area. The number of bytes moved on each pass
- ; is the minimum of 16k, the number of bytes remaining to be copied, the number
- ; of bytes left on the source page (pg0) and the number of bytes remaining on
- ; the destination page (pg1) from its current offset to the 16k boundary. The
- ; source logical page is mapped to physical page 0 and the destination logical
- ; page is mapped to physical page 1 except when the source and destination
- ; logical pages coincide. Then the destination page is not mapped by the EMS
- ; mapping function; instead it shares physical page 0 with the source page.
- ; This is done in case the EM manager does not support aliasing (as some EMS
- ; emulators don't).
-
- delpg0 dw ?
- delpg1 dw ?
-
- endpg proc near ; Sets dx to the offset of the byte just
- cmp ax,cs:lastpg ; beyond the last byte of the EMS page
- je pglast ; (contained in ax) devoted to the
- mov dx,k16 ; scroll buffer.
- ret
- pglast: mov dx,cs:lastofs
- ret
- endpg endp
-
- setpg0 proc near ; map the source page
- mov ax,4400h
- mov bx,cs:delpg0
- call ems
- ret
- setpg0 endp
-
- setpg1 proc near ; map the destination page
- mov ax,cs:delpg0
- cmp ax,cs:delpg1
- je pg1set
- mov ax,4401h
- mov bx,cs:delpg1
- call ems
- pg1set: ret
- setpg1 endp
-
- setdelpg0 proc near ; Sets pg0 from variable delpg0. The
- mov ax,cs:delpg0 ; routine returns the number of bytes
- call endpg ; remaining to be copied from the source
- cmp si,dx ; page in ax.
- jne pg0same
- mov ax,cs:lastpg
- cmp ax,cs:delpg0
- je sdp0zero
- inc cs:delpg0
- jmps sdp0set
- sdp0zero: mov cs:delpg0,0
- sdp0set: call setpg0
- sub si,si
- mov ax,ds:delpg0
- call endpg
- mov ax,dx
- ret
- pg0same: mov ax,dx
- sub ax,si
- ret
- setdelpg0 endp
-
- getpgofs proc near ; Returns in bx the offset within the
- mov ax,cs:delpg0 ; page frame segment where pg1, the
- cmp ax,cs:delpg1 ; destination page, will be mapped.
- je zerofs
- mov bx,k16
- ret
- zerofs: sub bx,bx
- ret
- getpgofs endp
-
- setdelpg1 proc near ; Sets a new destination page if the
- call setpg1 ; destination bytes of the current page
- call getpgofs ; have been filled with bytes from the
- mov ax,cs:delpg1 ; source page(s). The di offset is set
- call endpg ; to physical page 0 if destination and
- cmp di,dx ; source pages share the same logical
- jne pg1same ; page number, otherwise physical page
- mov ax,cs:lastpg ; 1 is used as the mapping for the
- cmp ax,cs:delpg1 ; distination page. The number of bytes
- je sdp1zero ; remaining to be filled to the end of
- inc cs:delpg1 ; the destination page is returned in
- jmps sdp1set ; ax.
- sdp1zero: mov cs:delpg1,0
- sdp1set: call setpg1
- call getpgofs
- mov di,bx
- mov ax,cs:delpg1
- call endpg
- mov ax,dx
- ret
- pg1same: mov ax,dx
- sub ax,di
- add di,bx
- ret
- setdelpg1 endp
-
- ; Num2delhi:num2dello stores the number of bytes in the lines to be deleted
- ; from the scroll buffer. Used by setloc routine.
-
- num2dello dw ?
- num2delhi dw ?
-
- num2del proc near ; Computes number of bytes to delete
- push ax ; placing the result in the double word
- push dx ; num2delhi:num2dello.
- mov ax,mark1ofs
- mov dx,mark1pg
- mov num2delhi,0
- mov num2dello,0
- n2dnxt: call bumpdxax
- add num2dello,linsiz
- adc num2delhi,0
- cmp dx,mark2pg
- jne n2dnxt
- cmp ax,mark2ofs
- jne n2dnxt
- pop dx
- pop ax
- ret
- num2del endp
-
- bumptr proc near ; Called by the routine setloc below
- add si,linsiz ; to increment the running pointer kept
- adc di,0 ; in di:si.
- cmp di,endofshi
- jne bumptrout
- cmp si,endofslo
- jne bumptrout
- sub si,si
- sub di,di
- bumptrout: ret
- bumptr endp
-
- ; The location pointer (lochi:loclo) is a temporary pointer that is set to one
- ; of the two pointers tophi:toplo or savhi:savlo so that the same routine,
- ; setloc, can serve to manipulate either one. The adjusted location pointer is
- ; then stored back to the pointer from which it came.
-
- loclo dw ?
- lochi dw ?
-
- ; The double word num2mov is used by delmk to contain the number of bytes to be
- ; moved (resulting in deletion of lines) within the scroll buffer.
-
- num2movlo dw ?
- num2movhi dw ?
-
- ; Setloc adjusts the loc pointer to a new value that accounts for the deletion
- ; of lines within the scroll buffer caused by delmk. Di:si is used to point
- ; to successive lines in the scroll buffer. Starting at the head of the scroll
- ; buffer, it is incremented to point to another scroll buffer line for every
- ; pass through each of the two loops in the routine. If the loc pointer is
- ; encountered first before either mark1 or mark2, then the routine returns
- ; leaving the loc pointer unchanged. Should mark1 be encountered first the
- ; routine jumps to the second loop. Now if the loc pointer is encountered
- ; before mark2, then it is set to mark1. Otherwise mark2 is encountered and
- ; the loc pointer is moved closer to the head by the number of bytes being
- ; deleted.
-
- setloc proc near
- mov ax,mark1ofs
- mov dx,mark1pg
- call unresolve
- mov si,headlo
- mov di,headhi
- jmps cmploc1
- bump1: call bumptr
- cmploc1: cmp di,lochi
- jne cmpmk1
- cmp si,loclo
- jne cmpmk1
- ret
- cmpmk1: cmp di,dx
- jne bump1
- cmp si,ax
- jne bump1
- mov ax,mark2ofs
- mov dx,mark2pg
- call unresolve
- jmps cmploc2
- cmpmk2: cmp di,dx
- jne bump2
- cmp si,ax
- jne bump2
- mov ax,num2dello
- mov dx,num2delhi
- sub loclo,ax
- sbb lochi,dx
- jns dmstout
- mov ax,endofslo
- mov dx,endofshi
- add loclo,ax
- adc lochi,dx
- dmstout: ret
- bump2: call bumptr
- cmploc2: cmp di,lochi
- jne cmpmk2
- cmp si,loclo
- jne cmpmk2
- mov ax,mark1ofs
- mov dx,mark1pg
- call unresolve
- mov loclo,ax
- mov lochi,dx
- ret
- setloc endp
-
- ; The sav pointer is used to save the location of the top pointer when the
- ; command is given to save the current location within the scroll buffer for
- ; later recall. 0ffffh in the high word of the sav pointer indicates it is
- ; uninitialized. It is (possibly) altered within the delmk routine due to the
- ; deletion of lines in exactly the same manner that the top pointer can be
- ; redefined by the removal of scroll buffer lines.
-
- savlo dw ?
- savhi dw -1
-
- ; Bufwrap is set to 1 when the buffer tail wraps to the head pointer. After
- ; that the head points one line further ahead of the tail in the scroll buffer.
- ; If delmk is used to delete every line from the scroll buffer, bufwrap must be
- ; reset to zero so that the savscr2ems routine will properly manage head and
- ; tail pointers.
-
- bufwrap db 0
-
- delmk proc near ; The procedure that implements the
- mov ax,mark2ofs ; deletion of marked text lines when the
- mov dx,mark2pg ; delete key is pressed.
- cmp mark1ofs,ax
- jne onlast?
- cmp mark1pg,dx
- jne onlast?
- ret
- onlast?: cmp dx,lastpg
- jne dodelete
- cmp ax,scrsavofs
- jb dodelete
- je mk22tail
- ret ; Return if a location in the current
- ; screen is marked.
- mk22tail: mov ax,taillo ; If mark2 is pointing to the first line
- mov dx,tailhi ; of the current screen (meaning that
- call resolve ; the last line marked was the line
- mov mark2ofs,ax ; before the tail pointer), then mark2
- mov mark2pg,dx ; is set to the tail. This makes it
- dodelete: call num2del ; possible to trace up to the tail when
- call unresolve ; bumping a buffer pointer one line at
- mov bx,taillo ; a time.
- mov cx,tailhi
- mov num2movlo,0
- mov num2movhi,0
- tailyet?: cmp dx,cx ; Count the number of bytes from mark2
- jne dmnxtlin ; (represented as absolute offset in
- cmp ax,bx ; dx:ax at the start of this section of
- jne dmnxtlin ; code) to the tail (in cx:bx). The
- jmps newtail ; count is accumulated in num2movhi:
- dmnxtlin: add ax,linsiz ; num2movlo.
- adc dx,0
- cmp dx,endofshi
- jne bump2mov
- cmp ax,endofslo
- jne bump2mov
- sub ax,ax
- sub dx,dx
- bump2mov: add num2movlo,linsiz
- adc num2movhi,0
- jmps tailyet?
- newtail: mov ax,mark1ofs ; The new tail will be num2mov bytes
- mov dx,mark1pg ; from the mark1 offset.
- call unresolve
- add ax,num2movlo
- adc dx,num2movhi
- cmp dx,endofshi
- jb storetail
- ja wraptail
- cmp ax,endofslo
- jb storetail
- wraptail: sub ax,endofslo
- sbb dx,endofshi
- storetail: mov taillo,ax
- mov tailhi,dx
- mov ax,toplo ; See about setting a new top pointer
- mov loclo,ax ; caused by the deletion of lines.
- mov ax,tophi
- mov lochi,ax
- call setloc
- mov ax,loclo
- mov toplo,ax
- mov ax,lochi
- mov tophi,ax
- cmp savhi,-1 ; Has the save pointer been set?
- je chk2mov ; No, check the number to move.
- mov ax,savlo ; See about setting a new sav pointer
- mov loclo,ax ; caused by the deletion of lines.
- mov ax,savhi
- mov lochi,ax
- call setloc
- mov ax,loclo
- mov savlo,ax
- mov ax,lochi
- mov savhi,ax
- chk2mov: mov ax,num2movlo
- or ax,num2movhi
- jz markisgone ; None to move.
- setdelptrs: mov si,mark2ofs
- push mark2pg
- pop delpg0
- call setpg0
- mov di,mark1ofs
- push mark1pg
- pop delpg1
- call setpg1
- mov es,pfseg
- push ds
- mov ds,pfseg
- jmps delfrst
- delnxt: call getpgofs
- sub di,bx
- delfrst: mov cx,k16 ; The number to move for each pass
- cmp cs:num2movhi,0 ; through the loop is the minimum of
- jne setdelpgs ; 16k, the number of remaining bytes to
- cmp cs:num2movlo,cx ; move, the number of bytes in the
- ja setdelpgs ; source page from si to the end of the
- mov cx,cs:num2movlo ; source page (returned in ax by the
- setdelpgs: call setdelpg0 ; call to setdelpg0), and the number of
- cmp ax,cx ; bytes in the destination page from di
- ja dodelpg1 ; to the end of that page (returned in
- mov cx,ax ; ax by the call to setdelpg1).
- dodelpg1: call setdelpg1
- cmp ax,cx
- ja delwords
- mov cx,ax
- delwords: push cx
- shr cx,1
- rep movsw
- pop cx
- sub cs:num2movlo,cx
- sbb cs:num2movhi,0
- mov ax,cs:num2movlo
- or ax,cs:num2movhi
- jz showmkgone
- jmps delnxt
- showmkgone: pop ds
- markisgone: mov ax,headlo
- mov dx,headhi
- cmp dx,tailhi
- jne resetmks
- cmp ax,taillo
- jne resetmks
- mov bufwrap,0 ; Reinitialize bufwrap when all lines
- resetmks: sub ax,ax ; are deleted from the scroll buffer.
- mov mark1ofs,ax ; Reset mark1 and mark2, then update
- mov mark1pg,ax ; the screen from the top pointer down.
- mov mark2ofs,ax
- mov mark2pg,ax
- mov ax,toplo
- mov dx,tophi
- call showattop
- ret
- delmk endp
-
- ; The savadj? flag is set to 1 if the head pointer encounters the sav pointer.
- ; It serves to insure that the sav pointer tracks the head pointer if ever the
- ; original sav location is pushed out of the scroll buffer.
-
- savadj? db ?
-
- ; savpo = save position, rstpo = restore position
-
- savpo proc near
- mov ax,toplo
- mov savlo,ax
- mov ax,tophi
- mov savhi,ax
- mov savadj?,0
- ret
- savpo endp
-
- rstpo proc near
- cmp savhi,-1 ; Can't restore to an uninitialized
- je rpout ; location.
- mov ax,savlo
- mov toplo,ax
- mov dx,savhi
- mov tophi,dx
- call showattop
- rpout: ret
- rstpo endp
-
- ;; note: specify which registers are allowed to be used in command routines
- ;; without being saved
-
- esc_enable db 0 ; The "e" command line switch sets this
- ; to 1 to enable the ESCape command
-
- escap proc near
- cmp esc_enable,1 ; Command line switch set?
- jne escap_out ; No, ESCape command not allowed
- mov pause,0 ; Yup, we're getting out
- push ds
- mov ax,40h
- mov ds,ax
-
- assume ds:biosdata
-
- and kbdstat,not slock ; reset Scroll Lock bit
- pop ds
-
- assume ds:code
-
- escap_out: ret
- escap endp
-
- freemarks proc near ; This routine is called to unmark all
- call markdata ; marked lines before WAS leaves the
- jnz freeum ; hold state.
- ret
- freeum: call setstuff ; If an area is marked set the stuff1
- call markarea ; and stuff2 pointers so that the area
- sub ax,ax ; marked will be feed to the keyboard
- mov mark1ofs,ax ; buffer.
- mov mark1pg,ax
- mov mark2ofs,ax
- mov mark2pg,ax
- ret
- freemarks endp
-
- chkmode proc near ; Check the video mode and return with
- push bx ; the zero flag set iff it is a text
- push ds ; mode.
- mov bx,40h
- mov ds,bx
-
- assume ds:biosdata
-
- cmp videomode,2
- je cmout
- cmp videomode,3
- je cmout
- cmp videomode,7
- je cmout
- cmout: pop ds
- pop bx
- ret
- chkmode endp
-
- assume ds:nothing
-
- staton db 0
- saveword dw ?
- stat0 dw no
- stat1 dw yes
-
- setstat proc near ; Destroys ax, si, di and es
- cmp staton,0 ; Show the status of scroll saving in
- je showstat ; the upper left corner of the screen.
- ret
- showstat: push ds
- push cs
- pop ds
-
- assume ds:code
-
- mov es,regen
- sub di,di
- mov si,ofs saveword
- mov ax,es:[di]
- mov [si],ax
- mov si,ofs stat1
- cmp saving,1
- je putstat
- mov si,ofs stat0
- putstat: lodsw
- stosw
- mov staton,1
- pop ds
-
- assume ds:nothing
-
- ret
- setstat endp
-
- rststat proc near ; destroys ax, si, di and es
- cmp staton,1 ; Remove the status indicator from the
- je killstat ; upper left corner of the screen by
- ret ; replacing it with the character and
- killstat: push ds ; attribute originally displayed there.
- push cs
- pop ds
-
- assume ds:code
-
- mov es,regen
- sub di,di
- mov si,ofs saveword
- lodsw
- stosw
- mov staton,0
- pop ds
-
- assume ds:nothing
-
- ret
- rststat endp
-
- ; The keytbl is a table of words that represent the byte pairs placed in the
- ; keyboard buffer by int 9 when a key is pressed. This table is scanned for a
- ; value matching a key found in the keyboard buffer by the code below. If a
- ; match is found, then it serves--after adjustment--as an offset into cmdtbl,
- ; a call table containing the addresses of routines that implement the command
- ; corresponding to the keypress. Thus the command keypresses represented by
- ; the word values in keytbl correspond one-for-one to the routines with their
- ; addresses in cmdtbl. This makes it extremely easy to add commands to the
- ; existing list.
-
- keytbl dw 4800h, 5000h, 4900h, 5100h, 4700h, 4f00h, 5200h, 4e2bh
- dw 4838h, 5032h, 4a2dh, 4b00h, 4b34h, 4d00h, 4d36h, 0e08h
- dw 5300h, 1c0dh, 000dh, 372ah, 092ah, 011bh
- cmdtbl dw linup, lindn, scrup, scrdn, hmscr, enscr, insrt, setmk
- dw linup, lindn, rstmk, movlt, movlt, movrt, movrt, setsv
- dw delmk, savpo, savpo, rstpo, rstpo, escap
- keytblsiz = cmdtbl - keytbl
-
- pause db 0
- inhold db 0
- textmode db ?
-
- ; The hold routine is where execution is sent by either of the WAS interrupt
- ; traps for int 8 or int 10h. Hold waits in a loop looking for keypresses that
- ; express commands and then executes them, but it eats the keypresses that have
- ; no associated command. The cursor is turned off each time through the loop
- ; in case a pop up TSR has left the cursor on before returning control to WAS.
-
- ;click proc near
- ; in al,61h ; get current value of speaker bit
- ; jmp $+2
- ; xor al,2 ; toggle bit
- ; out 61h,al ; move speaker
- ; jmp $+2
- ; ret
- ;click endp
-
- hold proc near ; destroys bx and ds
- mov inhold,1
- push ax
- push cx
- mov ax,ss
- mov bx,sp
- mov cx,cs
- mov ss,cx
- mov sp,ofs thestack
- sti
- push ax
- push bx
- push dx
- push si
- push di
- push bp
- push es
- push cs
- pop ds
- mov stuff?,0
- mov textmode,0
- call setvideo
- call chkmode
- jne stay
- mov textmode,1
- cld
- call savscr ; Save user's current screen.
- call settop ; Set the top pointer to buffer tail.
- mov bx,40h
- mov ds,bx
- stay: mov ax,40h
- mov ds,ax
-
- assume ds:biosdata
-
- cmp textmode,1
- jne key?
- call curoff
- test kbdstat,alt
- jz blnkstat
- call setstat
- jmps key?
- blnkstat: call rststat
- key?: cli
- mov bx,kbdhead ; Read keypresses from the keyboard
- mov ax,[bx] ; buffer; eat them if they are not
- cmp ax,2[bx] ; commands to WAS.
- jne holdchr
- sti
- cmp pause,0
- jne stay
- jmps exithold
- holdchr: mov bx,2[bx] ; Found a keypress. Place it in ax and
- sub bx,2 ; remove it from the keyboard buffer.
- cmp bx,kbdstart
- jae getkey
- mov bx,kbdend
- sub bx,2
- getkey: mov ax,[bx]
- push bx
- mov bx,kbdtail
- pop [bx]
- sti
- cmp textmode,1
- jne stay
- cmp al,0e0h
- jne specascii? ; A special ASCII keypress?
- sub al,al
- specascii?: cmp ah,0e0h
- jne chkkey
- sub ah,ah
- chkkey: mov di,ofs keytbl
- mov cx,keytblsiz/2
- push cs
- pop es
- repne scasw ; Is the keypress a recognized command?
- je docommand ; Yes, call the corresponding routine.
- jmps stay
- docommand: mov si,di
- add si,keytblsiz-2
- push cs
- pop ds
- ; call click
- call [si]
- jmps stay
- exithold: cmp textmode,1
- jne holdout
- call curon
- push cs
- pop ds
- call freemarks
- call rstscr
- holdout: pop es
- pop bp
- pop di
- pop si
- pop dx
- pop bx
- pop ax
- cli
- mov ss,ax
- mov sp,bx
- pop cx
- pop ax
-
- assume ds:nothing
-
- mov inhold,0
- ret
- hold endp
-
- ascscn: ; The scan codes for the corresponding ASCII codes; accessed using the
- ; ASCII code as an index into the table (via xlat). This table is used
- ; to generate the appropriate keypress to stuff into the keyboard buffer
- ; whenever the keyboard buffer is feed with text from the scroll buffer.
-
- db 0, 0, 0, 0, 0, 0, 0, 0, 14, 15, 0, 0, 0, 28, 0, 0, 0, 0, 0
- db 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 57, 2, 40, 4, 5, 6
- db 8, 40, 10, 11, 9, 13, 51, 12, 52, 53, 11, 2, 3, 4, 5, 6, 7, 8, 9
- db 10, 39, 39, 51, 13, 52, 53, 3, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37
- db 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27, 7
- db 12, 41, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50, 49, 24, 25, 16
- db 19, 31, 20, 22, 47, 17, 45, 21, 44, 26, 43, 27, 41
-
- getpage proc near ; Map an EMS page.
- mov ax,4400h
- mov bx,dx
- call ems
- ret
- getpage endp
-
- nextsi dw ?
-
- ; The keysleft variable is initialized to 0 by the setstuff routine as is the
- ; crflag variable.
-
- lodkey proc near ; Returns a keypress from marked text.
- cmp keysleft,0 ; The keysleft variable contains the
- jne akey ; number of text characters remaining
- push cx ; to be read from a line of formerly
- push si ; marked text. When lodkey is called
- flag0?: cmp crflag,0 ; and keysleft is zero, then a new line
- jne flag1? ; is checked for characters and their
- mov bx,si ; number is placed in keysleft. This
- add bx,linsiz ; number is the number of characters on
- mov nextsi,bx ; the line between the column offset in
- jmps prepline ; the variable margin for a number of
- flag1?: cmp crflag,1 ; characters in the variable lnwdth
- jne flag2? ; minus any trailing spaces. Crflag
- nxtlin: mov crflag,2 ; controls execution through the code.
- pop si ; Initially it is 0 so it causes nextsi
- mov si,nextsi ; to be initialized. Nextsi is the
- cmp si,k16 ; offset of the next line in the area
- jb nextsiok ; formerly marked. Then the code jumps
- sub si,k16 ; to prepline where keysleft is set and
- inc dx ; crflag is set to 1. The next time
- call getpage ; lodkey is called and keysleft is 0
- nextsiok: mov bx,si ; crflag being 1 causes the return of
- add bx,linsiz ; a carriage return keypress. Crflag
- mov nextsi,bx ; is set to 2. When keysleft is zero
- pop cx ; and crflag is 2, then si is set to
- stc ; the address of the next line, crlf is
- ret ; set to 1, and the routine returns
- flag2?: cmp crflag,2 ; with the carry flag set since no
- jne prepline ; keypress is returned. Subsequent
- mov al,cr ; calls to lodkey start the process all
- inc crflag ; over again only no initialization
- pop si ; since crflag is never 0 again unless
- pop cx ; the process starts over from the
- ret ; beginning.
- akey: lodsw
- dec keysleft
- ret
- prepline: add si,margin
- cmp si,k16 - 160
- jbe countspaces
- mov bx,dx
- inc bx
- mov ax,4401h
- call ems
- countspaces: mov cx,lnwdth
- push cx
- sub bx,bx
- space?: lodsw
- cmp al,' '
- je bumpbx
- sub bx,bx
- loop space?
- jmps setline
- bumpbx: inc bx
- loop space?
- setline: pop cx
- sub cx,bx
- jcxz nxtlin
- mov keysleft,cl
- mov crflag,1
- pop si
- add si,margin
- pop cx
- jmps akey
- lodkey endp
-
- getstfkey proc near ; Make a keypress to be stuffed into
- gskfirst: cmp si,stuff2ofs ; the keyboard buffer by translating
- jne gskanother ; text in the formerly marked area into
- cmp dx,stuff2pg ; keypress data.
- jne gskanother
- stc
- mov stuff?,0
- ret
- gskanother: cmp si,k16
- jne gskkey
- inc dx
- sub si,si
- sub nextsi,k16
- call getpage
- gskkey: call lodkey ; Get a keypress from EMS memory that
- jc gskfirst ; was formerly marked text.
- cmp al,127 ; If the ASCII code is 127 or over,
- jb ascii
- sub ah,ah ; then the main byte is zero.
- jmps gskout
- ascii: mov ah,al ; Otherwise, we use the ascscn table to
- push ds ; determine the scan code value of the
- push cs ; corresponding ASCII character.
- pop ds
- mov bx,ofs ascscn
- xlat
- xchg al,ah
- pop ds
- gskout: clc
- ret
- getstfkey endp
-
- assume ds:biosdata, es:biosdata
-
- stuffit? proc near ; destroys ax, bx, ds and es
- mov pause,1 ; Stuffit? is called by the replacement
- push dx ; int 8 routine at every clock tick
- push si ; that occurs whenever the scroll lock
- mov si,stuff1ofs ; state is not active. If there is
- mov dx,stuff1pg ; text remaining to be stuffed into the
- mov bx,kbdhead ; keyboard buffer, then the stuff?
- mov ax,[bx] ; variable is 1 else 0. That decides
- cmp ax,2[bx] ; the calling of stuffit? by the int 8
- je stuffit?ok ; routine. Stuffit? will not stuff
- stuffit?out: pop si ; keypresses into the keyboard buffer
- pop dx ; unless it is empty.
- mov pause,0
- ret
- stuffit?ok: sti
- push cx
- push di
- call savcntx ; Save the EMS context.
- call getpage
- mov di,kbdstart
- mov ds,pfseg
- cld
- mov cx,15 ; Stuff up to 15 keypresses.
- nxtstf: call getstfkey ; Getstfkey returns with the carry set
- jc stuffit?done ; if there are no more keypresses to
- stosw ; stuff.
- loop nxtstf
- stuffit?done: mov stuff1ofs,si
- mov stuff1pg,dx
- mov bx,kbdhead
- push es
- pop ds
- cli
- push kbdstart ; Update keyboard buffer head and tail.
- pop [bx]
- mov 2[bx],di
- sti
- call rstcntx ; Restore the EMS context.
- pop di
- pop cx
- jmps stuffit?out
- stuffit? endp
-
- chk8259 proc near ; Check the 8259A interrupt controller
- push ax ; for in service interrupts.
- mov al,0bh
- cli
- out 20h,al
- jmp $+2
- in al,20h
- jmp $+2
- sti
- or al,al
- pop ax
- ret
- chk8259 endp
-
- slock2bl proc near ; Return in bl the state of the Scroll
- mov bx,40h ; Lock bit in the keyboard status byte.
- mov ds,bx ; (Also sets up the ds register for
- ; addressing BIOS data variables. Used
- assume ds:biosdata ; even later in stuffit? routine.)
-
- mov bl,slock
- and bl,kbdstat
- ret
- slock2bl endp
-
- ; The int 8 vector as WAS saw it before installing it's own int 8 handler.
-
- old8 label dword
- old8lo dw ?
- old8hi dw ?
-
- ; The enabled? flag helps to implement the '+' and '-' switches.
-
- enabled? db 1 ; We're active by default.
-
- ; The in10 flag is set to 1 by the trapped int 10h routine so that the spliced
- ; in int 8 routine does not call hold while int 10h is executing. If hold was
- ; allowed to be called while int 10h was in progress, then there would be times
- ; that a halt would be called when int 10h was in the process of scrolling the
- ; screen and occationally a line would appear twice on the screen and yet not
- ; really be there--an illusion. (Say a text file was being displayed using the
- ; DOS TYPE command. A text line might appear twice on the display whereas, in
- ; fact, the line does not appear twice in the file being TYPEd.)
-
- in10 db 0
-
- new8 proc far
- pushf ; Call the former int 8 routine
- call old8
- cmp enabled?,1 ; Are we active?
- je our8 ; Yes, do our thing.
- iret ; No, bye.
- our8: push bx
- push ds
- call slock2bl ; (sets ds to biosdata)
- ; If scroll lock state is not on
- jz chkstuff ; check for keyboard buffer stuffing.
- cmp pause,0 ; Scroll lock is active and we're not
- je hold? ; holding, can we?
- jmps new8out ; We're holding get out.
- hold?: cmp in10,0 ; Refuse to hold while in int 10h.
- jne new8out
- call chk8259
- jnz new8out ; Or when there's a pending interrupt.
- mov pause,bl
- call hold ; Let's go into holding mode.
- new8out: pop ds
- pop bx
- iret
- chkstuff: mov pause,0
- cmp stuff?,1
- jne new8out
- cmp inhold,0 ; Perform some reasonable checks, then
- jne new8out ; stuff the keyboard buffer with 15
- call chk8259 ; keypresses at a time.
- jnz new8out
- push ax
- push es
- push ds
- pop es ; put es to BIOS data area also
- call stuffit?
- pop es
- pop ax
- jmps new8out
- new8 endp
-
- savsiz dw ? ; Number of screen bytes to save.
-
- ; The following code up to the end of resident code all applies to the spliced
- ; in int 10h routine below.
-
- assume ds:code
-
- ; If the head pointer surpasses the sav pointer when it (head ptr) is updated
- ; by savscr2ems, then the sav pointer must be set to the new head pointer. The
- ; lasthead pointer and the chksavptr routine work together to do this.
-
- lastheadlo dw ?
- lastheadhi dw ?
-
- chksavptr proc near
- cmp savhi,-1 ; Has a sav location been stored yet?
- jne savpassed? ; Yes, has sav been passed by head?
- ret
- savpassed?: cmp savadj?,1
- jne chksav ; Not before, maybe now?
- setsav2head: mov ax,headlo
- mov savlo,ax
- mov ax,headhi
- mov savhi,ax
- ret
- chksav: mov ax,lastheadlo
- mov dx,lastheadhi
- cmp2head: cmp dx,headhi
- jne cmp2sav
- cmp ax,headlo
- jne cmp2sav
- ret
- cmp2sav: cmp dx,savhi
- jne cspbump
- cmp ax,savlo
- jne cspbump
- mov savadj?,1
- jmps setsav2head
- cspbump: add ax,linsiz
- adc dx,0
- cmp dx,endofshi
- jne cmp2head
- cmp ax,endofslo
- jne cmp2head
- sub ax,ax
- sub dx,dx
- jmps cmp2head
- chksavptr endp
-
- savscr2ems proc near ; Transfer savsiz bytes from the screen
- mov ax,taillo ; to the EMS scroll buffer.
- mov dx,tailhi
- call resolve
- mov di,ax
- cmp dx,lastpg
- jne savem
- mov bx,ax ; If the tail is in the last page and
- add bx,savsiz ; savsiz is more than would fit within
- cmp bx,lastofs ; that portion of the last page devoted
- jbe savem ; to the scroll buffer, then the number
- mov bx,lastofs ; of bytes to be saved is broken into
- sub bx,ax ; two pieces. The first piece is saved
- mov ax,savsiz ; to EMS by a call to savem. The second
- sub ax,bx ; piece is saved by falling through the
- push ax ; code after savem.
- mov savsiz,bx
- call savem
- pop savsiz
- savem: mov ax,4400h ; access page(s) to store screen
- mov bx,dx
- call ems
- mov bx,di
- add bx,savsiz
- cmp bx,k16
- jbe dosave
- mov ax,4401h ; If the savsiz plus the offset of the
- inc dx ; resolved tail goes beyond the first
- mov bx,dx ; physical page, then the second
- call ems ; physical page has the next logical
- dosave: mov cx,savsiz ; page mapped to it.
- add taillo,cx
- adc tailhi,0
- shr cx,1
- call scr2ems
- mov ax,headlo
- mov lastheadlo,ax
- mov ax,headhi
- mov lastheadhi,ax
- mov ax,taillo
- mov bx,tailhi
- cmp bx,endofshi
- jne chkwrap
- cmp ax,endofslo
- jne chkwrap
- sub dx,dx ; Whenever the tail wraps to zero the
- sub di,di ; head is set to one line beyond
- mov taillo,dx ; location 0.
- mov tailhi,dx
- mov headlo,linsiz
- mov headhi,dx
- mov bufwrap,1
- jmps ss2eout
- chkwrap: cmp bufwrap,1
- jne ss2eout
- add ax,linsiz ; After the tail wraps back to the
- adc bx,0 ; beginning of the scroll buffer, the
- mov headlo,ax ; head is maintained one line above
- mov headhi,bx ; the tail.
- cmp bx,endofshi
- jne ss2eout
- cmp ax,endofslo
- jne ss2eout
- sub ax,ax
- mov headlo,ax
- mov headhi,ax
- ss2eout: call chksavptr
- ret
- savscr2ems endp
-
- sav2ems proc near ; destroys ax, bx, cx, dx, and ds
- call chkmode ; Save only when text modes in effect.
- je modeok
- ret
- modeok: push ds
- push ax
- mov ax,40h
- mov ds,ax
- pop ax
-
- assume ds:biosdata
-
- cmp videofs,0 ; Save only from first video page
- pop ds
-
- assume ds:code
-
- je cansav
- ret
- cansav: push es ; For the purpose of this screen saving
- push si ; routine all commands that scroll
- push di ; lines off the top of the screen have
- pushf ; been converted to scroll commands.
- push ax
- call savcntx ; Save the EMS context.
- pop ax
- cld
- or ah,ah
- jz modeset ; A mode set is converted to a scroll.
- s2ein: cmp dl,lastcol ; Save only full width scrolls.
- jb s2eout
- or cl,cl ; ditto
- jnz s2eout
- sub bh,bh
- mov bl,dh
- sub bl,ch
- inc bl ; Now bx has number of rows to save.
- or al,al
- jz setsavparams
- mov bl,al ; Unless al contains a row count.
- setsavparams: mov ax,bx
- mov bx,linsiz
- mul bx
- mov savsiz,ax ; Store bytes to save to EMS,
- mov al,ch
- sub ah,ah
- mul bx
- mov si,ax ; and offset of those bytes to si.
- call savscr2ems
- s2eout: call rstcntx ; Restore ems context.
- popf
- pop di
- pop si
- pop es
- ret
- modeset: push ds
- mov ax,40h
- mov ds,ax
-
- assume ds:biosdata
-
- mov ax,600h
- sub cx,cx
- mov dh,numrows
- mov dl,lastcol
- restoreds: pop ds
- jmps s2ein
- sav2ems endp
-
- evga db 0
-
- setvideo proc near ; This item gets and saves in variables
- push ax ; a number of valuable video parameters.
- push bx ; The pointsize (character height) is
- push cx ; obtained because it is needed when
- push dx ; properly restoring the cursor. Regen
- push ds ; is set as the location of the current
- mov ax,40h ; screen buffer which can be other than
- mov ds,ax ; page 0. Scrolled off lines are not
- ; saved from any page but page 0, but
- assume ds:biosdata ; they can be viewed while any video
- ; page is current.
- mov al,24
- cmp evga,1
- jne svrows
- mov al,numrows
- svrows: sub ah,ah
- inc ax
- mov numlines,ax
- mov bx,linsiz
- mul bx
- mov scrnsiz,ax
- add ax,scrsavofs
- mov lastsavofs,ax
- mov monochrome,0
- mov ax,0b800h
- mov bl,8
- cmp crtport,3d4h
- je setregen
- mov monochrome,1
- mov ax,0b000h
- mov bl,14
- setregen: mov regen,ax
- mov pointsize,bl
- mov ax,videofs
- mov cl,4
- shr ax,cl
- add regen,ax
- cmp evga,1
- jne svout
- cmp crtport,3b4h
- je svout
- mov ax,charhigh
- mov pointsize,al
- svout: pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- setvideo endp
-
- assume ds:nothing
-
- old10 label dword
- old10lo dw ?
- old10hi dw ?
- double db 0 ; Byte is set to 1 if d (double) switch
- ; is specified on the command line.
- ; (See documentation for details.)
-
- new10 proc far
- cmp ax,7b1eh ; This tidbit tells the caller (if ax
- jnz do10 ; and bx are right on entry) that this
- cmp bx,3d8fh ; routine (and therefore WAS) has been
- jnz do10 ; loaded. It's how WAS detects for a
- xchg ax,bx ; prior load of itself.
- push cs ; Tell caller where we are by setting
- pop es ; es to the cs of resident code.
- iret
- do10: cmp enabled?,1 ; Are we active?
- je our10 ; Yes, do our thing.
- jmp old10 ; No, pass it on.
- our10: mov in10,1 ; WAS will not call hold from within
- push ax ; this code because of this flag.
- push bx
- push cx
- push dx
- push ds
- or ah,ah ; Save screen if mode set.
- jz savit
- cmp ah,6 ; Save if scrolling.
- je savit
- cmp ah,0eh ; The TTY scrolling gets special
- je tty ; handling.
- call10: pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- pushf
- call old10
- call setvideo ; Any changes in video parameters are
- push bx ; now updated.
- push ds
- call slock2bl ; If the scroll lock state is not zero,
- jz new10out ; then maybe we can call hold.
- call chk8259 ; Check 8259A for in service interrupts.
- jnz new10out
- cmp inhold,0 ; In hold state already? (Could be. A
- jne new10out ; pop-up routine may do an int 10h.)
- mov pause,bl ; All's well so set pause and call hold.
- call hold
- new10out: pop ds
- pop bx
- mov in10,0
- iret
- savit: push cs
- pop ds
- cmp saving,1
- jne tocall10
- call sav2ems
- tocall10: jmps call10
- tty: cmp al,7 ; Not concerned about BELL,
- je call10
- cmp al,8 ; BACKSPACE
- je call10
- cmp al,13 ; or RETURN
- je call10
- mov cx,40h
- mov ds,cx
-
- assume ds:biosdata
-
- mov bl,bh ; The code (in sav2ems) does not allow
- sub bh,bh ; the saving of scrolled lines from
- shl bx,1 ; video pages other than page 0, but
- mov cx,cursorpos[bx]; the code here is going to try in case
- cmp al,lf ; other video pages are enabled at some
- jne lastcol? ; later date (say by a command line
- cmp ch,numrows ; switch).
- jne call10
- cmp double,1 ; is the double switch set?
- je call10 ; yes, no scroll for tty line feed
- savalin: mov ax,601h ; Interpret it as a scroll function.
- sub cx,cx
- mov dx,lastcol
- jmps savit
- lastcol?: cmp cl,lastcol ; If cursor is in the last column, then
- je savalin ; the screen will scroll when the
- jmps call10 ; character is written.
- new10 endp
-
- ; resident code ends here
-
- instmsg db cr,lf, 'WAS is already installed. Only +, -, or v switches are valid now.', cr,lf, '$'
- noemmmsg db cr,lf, "Cannot find Expanded Memory Manager.", cr,lf,'$'
- nobufmsg db cr,lf, 'No buffer specified or invalid specification.', cr,lf,'$'
- notenuf db cr,lf, "Not enough EMS memory for size of buffer specified.", cr,lf,'$'
- badsavmsg db cr,lf, "Invalid maximum lines per screen specified.",cr,lf,'$'
- installed db cr,lf, "WAS v",ver," Copyright 1990 by Charles Lazo III", cr,lf,'$'
-
- assume ds:code
-
- new db 1 ; If new = 1 then WAS.COM is freshly
- ; assembled, i.e., the coded summary
- ; file has not yet been annexed to
- ; WAS.COM.
- sumfile db "W-DOC",version,".SUM", 0
- nosumfile db cr,lf,"File W-DOC",version,".SUM cannot be opened.",cr,lf,'$'
- sumhandle dw ? ; file handle of coded summary file
- sumsize dw ? ; size of coded summay file
- wasfile db "WAS.COM", 0
- nowasfile db cr,lf,"The file WAS.COM cannot be opened.",cr,lf,'$'
-
- getswitch proc near ; A routine to detect the presence of
- mov bx,80h ; a switch character on the command
- mov cl,[bx] ; line. Al contains the lowercase
- or cl,cl ; character or symbol to be looked for.
- jz nocmd ; If lowercase not found it then looks
- push es ; for the capital as well. If the
- push cs ; switch is found, the routine returns
- pop es ; with the zero flag set and di points
- sub ch,ch ; to the first character after the
- mov di,82h ; switch.
- repne scasb
- je gsout
- mov cl,[bx]
- sub ch,ch
- mov di,82h
- cmp al,'a'
- jb gsout ; It's not a lowercase character.
- cmp al,'z'
- ja gsout ; ditto.
- and al,0dfh ; Convert to uppercase.
- repne scasb
- gsout: pop es
- ret
- nocmd: or bx,bx
- ret
- getswitch endp
-
- deci2bin proc near ; Convert ASCII decimal number at ds:di
- mov si,di ; to binary value in bx
- mov cx,10
- sub ah,ah
- sub bx,bx
- digit: lodsb
- cmp al,'0'
- jb d2bout
- cmp al,'9'
- ja d2bout
- sub al,'0'
- xchg ax,bx
- mul cx
- jo d2bout
- xchg ax,bx
- add bx,ax
- jc d2bout
- jmps digit
- d2bout: ret
- deci2bin endp
-
- start_stop db 0
-
- temp8 proc far
- inc start_stop
- jmp old8
- temp8 endp
-
- ; Execution starts here after jump from entry point.
-
- start: push es ; The little int 8 splice in routine
- mov ax,3508h ; above allows the determination of a
- int 21h ; double word count value that will
- mov old8hi,es ; allow timing intervals to be the same
- mov old8lo,bx ; no matter the speed of the CPU this
- ; program is run on. The count is for
- mov dx,ofs temp8 ; the duration of one clock tick or
- mov ax,2508h ; about 1/18 of a second. This count
- int 21h ; is divided by a power of 2 constant,
- ; pwr2div. The resulting count is used
- sub ax,ax ; in the procedure called interval at
- sub dx,dx ; the top of this file.
- next_test: cmp start_stop,1
- je do_count
- jmps next_test
-
- do_count: cmp start_stop,2
- je divdown
- inc ax
- jnz do_count
- inc dx
- jnz do_count
-
- divdown: mov cx,pwr2div
- divagain: shr dx,1
- rcr ax,1
- loop divagain
- mov countlo,ax
- mov counthi,dx
- mov start_stop,0 ; Don't want WAS.COM updated (when the
- ; summary file is annexed) without this
- ; set to zero.
- push ds
- mov ax,2508h ; Now the former int 8 is replaced in
- lds dx,old8 ; case we have to exit due to an error.
- int 21h
- pop ds
- pop es
-
- cmp new,1 ; The new flag will be set to 1 if WAS
- je test_s ; .COM is freshly assembled. It then
- jmp chkinst ; needs to annex the command summary
- test_s: mov al,'s' ; file. See the description of the
- call getswitch ; process in the summary message at the
- je opensum ; bottom of this source file.
- jmp showsummary
- opensum: mov ax,3d00h ; First open the command summary file.
- mov dx,ofs sumfile ; The summary file is coded by packing
- int 21h ; spaces to reduce its size to about
- jnc findsumsize ; a third of its uncompressed size.
- mov ah,9 ; If it can't be opened, say so and
- mov dx,ofs nosumfile
- mov al,1 ; exit with error code 1.
- jmp errexit
- findsumsize: mov sumhandle,ax
- mov bx,ax
- mov ax,4202h ; Find size of file using set file
- sub cx,cx ; pointer call.
- sub dx,dx
- int 21h
- mov sumsize,ax ; Preserve size of coded summary file
- mov ax,4200h ; Now we must set the file pointer back
- mov bx,sumhandle ; to the beginning of the file.
- sub cx,cx
- sub dx,dx
- int 21h
- mov ah,3fh ; Then we read it into the memory now
- mov bx,sumhandle ; containing the description of what is
- mov cx,sumsize ; necessary to do all this.
- mov dx,ofs summary
- int 21h
- mov ax,3d01h ; Now open WAS.COM for writing.
- mov dx,ofs wasfile
- int 21h
- jnc rewritewas
- mov ah,9 ; Say so and exit if can't find it in
- mov dx,ofs nowasfile; the current directory.
- mov al,2 ; exit with error code 3.
- jmp errexit
- rewritewas: mov new,0 ; After rewrite WAS.COM is no longer
- mov bx,ax ; "new".
- mov ah,40h
- mov dx,100h ; Code saved starts after the PSP.
- mov cx,ofs summary
- sub cx,dx
- add cx,sumsize
- int 21h ; Write coded summary to WAS.COM.
- coolexit: mov ax,4c00h ; No problems, return code = 0.
- int 21h
- showsummary: mov ah,9 ; Show user how to use 's' switch.
- mov dx,ofs summary
- int 21h
- jmps coolexit
-
- chkinst: mov ax,7b1eh ; Is WAS presently installed?
- mov bx,3d8fh
- int 10h
- sub bx,ax
- sub bx,ax
- jnz install ; no, go for install
-
- assume es:code
-
- mov al,'+' ; Check for either '+' or
- call getswitch
- jne chkminus
- mov es:enabled?,1
- jmps coolexit
-
- chkminus: mov al,'-' ; minus or
- call getswitch
- jne chkversion
- mov es:enabled?,0
- jmps coolexit
-
- chkversion: mov al,'v' ; version switches.
- call getswitch
- jne present
- mov ah,9
- mov dx,ofs installed; Show version message
- int 21h
- jmps coolexit
-
- assume es:nothing
-
- present: mov dx,ofs instmsg ; WAS is already installed and no '+'
- mov al,3 ; or '-' or 'v' switch found.
- jmps errexit ; So exit with error message.
-
- noemm: mov dx,ofs noemmmsg ; Message and exit if no EMM manager is
- mov al,4 ; installed.
- jmps errexit
-
- badsavsiz: mov dx,ofs badsavmsg; Message and exit of screen lines to
- mov al,5 ; save is too large.
- jmps errexit
-
- nobuf: mov dx,ofs nobufmsg ; Message and exit if no scroll back
- mov al,6 ; buffer has been specified, or if
- jmps errexit ; invalid specification has been made.
-
- errexit: mov ah,9 ; Send message at ds:dx, then exit with
- push ax ; error code in al.
- int 21h
- call buzz
- pop ax
- mov ah,4ch
- int 21h
-
- emmsig db 'EMMXXXX0' ; signature of expanded memory manager
-
- install: mov ax,3567h ; check for presence of EMM
- push es
- int 21h
- mov di,10
- mov si,ofs emmsig
- mov cx,4
- rep cmpsw
- pop es
- jne noemm ; error exit if not there
-
- mov al,'l'
- call getswitch
- jne getmem ; no 'l' switch, check 'b' switch
- call deci2bin
- jo badsavsiz ; invalid screen save size
- cmp bx,minlines
- jb badsavsiz ; not less than minimum screen lines
- cmp bx,maxlines ; musn't be over maximum screen lines
- ja badsavsiz
- mov ax,linsiz
- mul bx
- inc ax
- mov scrsavsiz,ax
- mov bx,k16
- sub bx,ax
- mov scrsavofs,bx
-
- getmem: mov al,'b' ; Find the 'b' switch.
- call getswitch
- jne nobuf ; If can't say so and exit.
- call deci2bin ; convert decimal size to binary in bx
- jo nobuf ; bad if overflow
- or bx,bx ; Error if zero.
- jz nobuf
- mov ax,bx
- dec ax ; Otherwize, the number of pages less
- mov lastpg,ax ; one is the last logical page.
- mov ah,43h ; Ask for this many EMS pages.
- int 67h
- or ah,ah ; Error?
- jz gotmem
- mov dx,ofs notenuf ; Yes, say there's not enough and exit.
- mov al,7
- jmps errexit
-
- gotmem: mov handle,dx
- mov ax,lastpg ; Do calculations to set lastofs.
- mov cx,k16 mod linsiz
- mul cx
- add ax,scrsavofs
- mov bx,linsiz
- div bx
- mov cx,scrsavofs
- mov lastofs,cx
- sub lastofs,dx
-
- mov cx,ax
- mov ax,k16 / linsiz
- mul lastpg
- add ax,cx
- mul bx
- mov endofslo,ax ; Could just as easily have called the
- mov endofshi,dx ; unresolve routine on lastpg:lastofs
-
- mov ah,41h ; Store away the page frame segment.
- int 67h
- mov pfseg,bx
-
- mov al,'n'
- call getswitch ; Is the 'n' switch present?
- je testevga ; Yes, don't place command summary into
- mov cx,lastpg ; the scroll buffer.
- inc cx
- cmp cx,4 ; Map however many pages necessary to
- jbe ofsbase ; read in entire command summary.
- mov cx,4
- ofsbase: mov dx,cx
- mov lastpage,-1 ; Set this value to something other
- mapnext: mov bx,dx ; than zero so that a page will be read
- sub bx,cx ; into physical page zero. (See ems
- mov al,bl ; procedure for details on the use of
- mov ah,44h ; lastpage variable.)
- call ems
- loop mapnext
- mov es,pfseg
- sub di,di
- mov si,ofs summary
- mov cx,sumsize ; number of coded bytes to process
- jmps nxtsumbyte ; begin command summary decoding
-
- lastattr db sumbg ; The last attribute used for a decoded
- ; character. It is the attribute used
- ; for decoded single spaces.
-
- nxtsumbyte: lodsb ; Get a coded, command summary byte.
- test al,80h ; Is it a coded series of spaces?
- jz getattr ; No, got character, now get attribute.
- push cx
- mov cl,al ; Calculate number of spaces to store.
- and cl,7fh
- sub ch,ch
- mov al,' ' ; Store spaces.
- cmp cx,2 ; And if it's more than two spaces...
- jbe setsumattr
- mov lastattr,sumbg ; use sumbg (summary background) attr.
- setsumattr: mov ah,lastattr ; else last character attribute is used
- rep stosw
- pop cx
- loop nxtsumbyte
- jmps dotailo
- getattr: mov ah,al ; character to ah
- lodsb ; attribute to al
- dec cx ; adjust count
- xchg ah,al ; character al, attribute ah
- mov lastattr,ah ; save attribute
- stosw
- loop nxtsumbyte
- dotailo: cmp endofslo,di
- jae setailo
- mov di,endofslo
- setailo: mov taillo,di
-
- testevga: mov ah,12h ; Test for presence of EGA or VGA.
- mov bx,1010h ; If present, then number of rows and
- int 10h ; character height will be found in the
- cmp bh,1 ; BIOS data area, otherwise they are
- ja initvideo ; already known depending upon MDA or
- mov evga,1 ; CGA.
-
- initvideo: call setvideo ; Be sure video parameters are set
- ; properly from the beginning.
-
- mov al,'-' ; Are we to be disabled from the getgo?
- call getswitch
- jne double? ; No, see if double switch is set.
- mov enabled?,0 ; Yes, reset active flag.
-
- double?: mov al,'d' ; Is the d switch set?
- call getswitch ; (see documentation)
- jne esc_enable? ; No, see if ESCape enable switch set.
- mov double,1 ; Yes, set double flag.
-
- esc_enable?: mov al,'e' ; Is the e switch set?
- call getswitch ; (ESCape key to release Scroll Lock?)
- jne goodbyenv ; No, carry on.
- mov esc_enable,1 ; Yes, ESCape key can cancel hold.
-
- goodbyenv: mov es,env ; Release memory of environment.
- mov ah,49h
- int 21h
-
- mov ax,2508h ; Set up new int 8,
- mov dx,ofs new8
- int 21h
-
- mov ax,3510h
- int 21h
- mov old10lo,bx
- mov old10hi,es
-
- mov ax,2510h ; and int 10h routines
- mov dx,ofs new10
- int 21h
-
- assume ds:biosdata
-
- push ds ; An older PC (with BIOS date before
- mov ax,40h ; the first XT BIOS) will not have
- mov ds,ax ; the locations kbdstart (40:80) and
- mov bx,kbdhead ; kbdend (40:82) initialized to the
- cmp wp[bx],3eh ; start and end respectively of the
- ja back2cs ; keyboard buffer. So we do that
- mov kbdstart,1eh ; initialization here if necessary
- mov kbdend,3eh ; because kbdstart and kbdend will be
- back2cs: pop ds ; used later in our code.
-
- assume ds:code
-
- mov dx,ofs installed; Display copyright message and TSR.
- mov ah,9
- int 21h
-
- mov dx,ofs instmsg + 15
- mov cl,4
- shr dx,cl
- mov ax,3100h
- int 21h
-
- summary: db cr,lf
- db " When WAS.COM has been newly assembled, linked, and exe2bined as is the case",cr,lf
- db " now (otherwise this message would not be displayed), you must run WAS with",cr,lf
- db " the 's' switch to force it to incorporate the W-DOC",version,".SUM file into WAS.COM",cr,lf
- db " so that this file (W-DOC",version,".SUM) can be available as a part of WAS to be put",cr,lf
- db " into the scroll back buffer as a command summary. The command summary is put",cr,lf
- db " into the scroll back buffer by default. That action is disabled by use of",cr,lf
- db " the 'n' (No summary) switch. (The file, W-DOC",version,".SUM, is a coded version of",cr,lf
- db " file SUMMARY.",version," [coded by packing spaces] which is in turn a file containing",cr,lf
- db " command summary information in a format that reflects its use, i.e., a video",cr,lf
- db " memory image. It includes text characters as well as character attributes.",cr,lf
- db " The program SPCPAK.EXE can be used to transform an edited version of the",cr,lf
- db " SUMMARY.",version," file into an updated W-DOC",version,".SUM file.) Now that you have a",cr,lf
- db " newly assembled copy of WAS.COM enter this command at the prompt (Be sure",cr,lf
- db " that you are running WAS.COM together in the same directory as the coded",cr,lf
- db " summary file, W-DOC",version,".SUM.):",cr,lf,lf
- db " WAS s",cr,lf,'$'
-
- code ends
- end entry