MS-DOS Kermit sources (Part 6 of 7)
Jim Knutson
knutson at ut-ngp.UUCP
Sat Oct 6 02:09:58 AEST 1984
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
all=FALSE
if [ $1x = -ax ]; then
all=TRUE
fi
/bin/echo 'Extracting msxwng.asm'
sed 's/^X//' <<'//go.sysin dd *' >msxwng.asm
public serini, serrst, clrbuf, outchr, coms, vts, dodel, ctlu
public cmblnk, locate, lclini, prtchr, dobaud, clearl
public dodisk, getbaud, beep, term, puthlp
public count, poscur, machnam, sendbr, putmod, clrmod
public setktab, setkhlp, xofsnt, showkey
include msdefs.h
false equ 0
true equ 1
ctrla equ 1 ; Control-A.
auxin equ 3
auxout equ 4
auxfil equ 3 ; file number of aux file.
iordy equ 6 ; input ready function
write equ 40h
wbios equ 88h
settrp equ 02h
clrtrp equ 03h
chrrdy equ 01h
txrdy equ 02h
rcvdat equ 1080h
rcvstat equ 1082h
rcvmod equ 1084h
rcvcmd equ 1086h
trdat equ 1088h
trmod equ 108ch
wrcmd equ 108eh
; mode bits
mod1 equ 4dh ; clock rate, 8 bits, 1 stop bit
mod2 equ 30h ; internal clock
; command register bits
txen equ 01h
dtr equ 02h
rxen equ 04h
brk equ 08h
clrerr equ 10h
rts equ 20h
datas segment public 'datas'
extrn drives:byte, flags:byte, trans:byte
extrn portval:word, port1:byte, port2:byte, swchar:byte
portin db 0
crlf db cr,lf,'$'
machnam db 'FIELD TEST Wang$'
noimp db cr,lf,'Command not implemented.$'
shkmsg db 'Not implemented.'
shklen equ $-shkmsg
xofsnt db 0 ; Say if we sent an XOFF.
xofrcv db 0 ; Say if we received an XOFF.
setktab db 0
setkhlp db 0
invseq db esc,'[7m$' ; Reverse video on.
nrmseq db esc,'[0m$' ; Reverse video off.
ivlseq db 79 dup (' '),cr,'$' ; Make a line inverse video
comphlp db cr,lf,'1 (COM1) 2 (COM2)$'
delstr db BS,' ',BS,'$' ; Delete string.
clrlin db cr,esc,'[K$'
tmp db ?,'$'
temp dw 0
temp1 dw ? ; Temporary storage.
temp2 dw ? ; Temporary storage.
; Entries for choosing communications port. [19b]
comptab db 04H
db 01H,'1$'
dw 01H
db 01H,'2$'
dw 00H
db 04H,'COM1$'
dw 01H
db 04H,'COM2$'
dw 00H
; variables for serial interrupt handler
source db bufsiz DUP(?) ; Buffer for data from port.
bufout dw 0 ; buffer removal ptr
count dw 0 ; Number of chars in int buffer.
bufin dw 0 ; buffer insertion ptr
telflg db 0 ; Are we acting as a terminal. [16] [17c]
clreol db esc,'[0K$'
blank db esc,'[H',esc,'[J$'
movcur db esc,'['
colno db 20 dup (?)
ten db 10
prthnd dw 0
ourarg termarg <>
; must parallel baud rate defs in pcdefs.
baudtab db 0ffh ; 45.5 baud (not supported)
db 0 ; 50
db 1 ; 75
db 2 ; 110
db 3 ; 134.5
db 4 ; 150
db 5 ; 300
db 6 ; 600
db 7 ; 1200
db 8 ; 1800
db 9 ; 2000
db 10 ; 2400
db 12 ; 4800
db 14 ; 9600
db 15 ; 19.2k
db 0ffh ; 38.4k (ha)
nbaud equ $-baudtab
qid dw ?
prtcnt dw ?
trqid dw ?
tmqid dw ?
brflg db ?
datas ends
code segment public
extrn comnd:near, dopar:near, prserr:near
assume cs:code,ds:datas
DODISK PROC NEAR
mov ah,gcurdsk ; Current disk value to AL.
int dos
mov dl,al ; Put current disk in DL.
mov ah,seldsk ; Select current disk.
int dos ; Get number of drives in AL.
mov drives,al
ret
DODISK ENDP
; Clear the input buffer before sending a packet. [20e]
CLRBUF PROC NEAR
mov ah,ioctl
mov bx,auxfil
mov al,iordy
int dos
cmp al,0ffh
jne clrb1 ; not ready, keep going
mov ah,auxin
int dos
jmp clrbuf ; read char and keep going.
clrb1: mov count,0
mov ax,offset source
mov bufin,ax
mov bufout,ax
ret
CLRBUF ENDP
; Common routine to clear to end-of-line. [19a]
CLEARL PROC NEAR
mov dx,offset clreol
mov ah,prstr
int dos
ret
CLEARL ENDP
; This routine should set the baud rate for the current port but it
; is actually done in SERINI.
dobaud proc near
ret
dobaud endp
; Send a break out the current serial port. Returns normally.
sendbr: push dx
push ax
push cx
push ds ; preserve data segment
mov ax,cs
mov ds,ax ; handler is in code segment
mov al,settrp
mov bx,txrdy ; interrupt on transmitter empty
mov cx,0 ; interrupt immediately
mov dx,offset sendb1 ; handler routine
int wbios
pop ds
mov trqid,bx
push ds
mov ax,cs
mov ds,ax
mov al,settrp
mov bx,0 ; 10 ms timer
mov cx,21 ; after 21 times - approx 200 ms.
mov dx,offset sendb2 ; timer interrupt
int wbios
pop ds
mov tmqid,bx
mov brflg,1
mov dx,rcvcmd
in al,dx ; Read command register.
or al,brk+txen ; Set send-break bit.
mov dx,wrcmd ; Write command register.
out dx,al
pause: cmp brflg,0
jne pause ; while non-zero, keep going
mov al,clrtrp ; clear the trap
mov bx,trqid
int wbios
mov al,clrtrp
mov bx,tmqid
int wbios
pop cx
pop ax
pop dx
ret
sendb1 proc far
ret
sendb1 endp
sendb2 proc far
push ax
push ds
mov ax,seg datas
mov ds,ax
mov brflg,0
mov dx,rcvcmd
in al,dx
and al,not (txen + brk)
mov dx,wrcmd
out dx,al
pop ds
pop ax
ret
sendb2 endp
; Write a line in inverse video at the bottom of the screen...
; the line is passed in dx, terminated by a $. Returns normally.
putmod proc near
push dx ; preserve message
mov dx,24 * 100H ; line 24
call poscur
mov dx,offset invseq ; put into inverse video
mov ah,prstr
int dos
pop dx
int dos
mov dx,offset nrmseq ; normal videw
int dos
ret ; and return
putmod endp
; Clear the mode line written by putmod. Returns normally.
clrmod proc near
mov dx,24 * 100H
call poscur
call clearl
ret
clrmod endp
; Put a help message one the screen in reverse video. Pass
; the message in AX, terminated by a null. Returns normally.
; The message is put wherever the cursor currently is located.
puthlp proc near
push ax
mov ah,prstr ; Leave some room before the message.
mov dx,offset crlf
int dos
mov dx,offset invseq ; Put into reverse video.
int dos
pop si ; Put message address here.
puth0: mov ah,prstr
mov dx,offset ivlseq ; Make line inverse video
int dos
puth1: lodsb
cmp al,0 ; Terminated with a null.
je puth2
mov dl,al
mov ah,conout
int dos
cmp al,lf ; Line feed?
je puth0 ; Yes, clear the next line.
jmp puth1 ; Else, just keep on writing.
puth2: mov dx,offset nrmseq ; Normal video.
mov ah,prstr
int dos
mov dx,offset crlf
int dos
ret
puthlp endp
outchr: push dx ; Save register.
mov al,ah
call dopar
mov dl,al
mov ah,auxout
int dos
pop dx
jmp rskp
; This routine blanks the screen.
CMBLNK PROC NEAR
mov ah,prstr
mov dx,offset blank
int dos
ret
CMBLNK ENDP
LOCATE PROC NEAR
mov dx,0 ; Go to top left corner of screen.
jmp poscur ; callret...
LOCATE ENDP
GETBAUD PROC NEAR
cld
mov dx,rcvmod
in al,dx
in al,dx ; get second mode word
and al,0fh ; isolate baud rate
mov cx,nbaud
mov di,offset baudtab
mov bx,ds
mov es,bx ; address correct segment
mov bx,portval
repne scasb ; look for baud rate
jne getb1 ; mystery baud rate...
sub di,offset baudtab + 1
mov [bx].baud,di ; store baud rate in comm area
ret ; and return
getb1: mov [bx].baud,-1 ; unknown baud rate
ret
GETBAUD ENDP
; skip returns if no character available at port,
; otherwise returns with char in al, # of chars in buffer in dx.
PRTCHR PROC NEAR
prtchx: cmp count,0
je prtch4 ; empty buffer, forget it.
mov si,bufout
lodsb
cmp si,offset source + bufsiz
jb prtch1
mov si,offset source
prtch1: mov bufout,si
dec count
push bx
mov bx,portval
cmp [bx].parflg,PARNON ; no parity?
je prtch3 ; then don't strip
and al,7fh ; else turn off parity
prtch3: mov dx,count ; chars left in buffer
pop bx
ret
prtch4: jmp rskp ; no chars...
PRTCHR ENDP
; Position the cursor according to contents of DX.
POSCUR PROC NEAR
mov ax,ds
mov es,ax ; address data segment!!!
cld
mov di,offset colno
mov al,dh ; row
inc al
call nout
mov al,';'
stosb
mov al,dl ; col
inc al
call nout
mov al,'H'
stosb
mov al,'$'
stosb
mov dx,offset movcur
mov ah,prstr
int dos ; print the sequence
ret
POSCUR ENDP
NOUT PROC NEAR
cbw ; extend to word
div byte ptr ten ; divide by 10
or al,al ; any quotient?
jz nout1 ; no, forget this
push ax ; save current result
call nout ; output high order
pop ax ; restore
nout1: mov al,ah ; get digit
add al,'0' ; make printable
stosb
ret ; put in buffer and return
NOUT endp
; Perform a delete.
DODEL PROC NEAR
mov ah,prstr
mov dx,offset delstr ; Erase weird character.
int dos
ret
DODEL ENDP
; Perform a Control-U.
CTLU PROC NEAR
mov ah,prstr
mov dx,offset clrlin
int dos
ret
CTLU ENDP
COMS PROC NEAR
mov dx,offset comptab
mov bx,offset comphlp
mov ah,cmkey
call comnd
jmp r
push bx
mov ah,cmcfm
call comnd ; Get a confirm.
jmp comx ; Didn't get a confirm.
nop
pop bx
mov flags.comflg,bl ; Set the comm port flag.
cmp flags.comflg,1 ; Using Com 1?
jne coms0 ; Nope.
mov ax,offset port1
mov portval,ax
ret
coms0: mov ax,offset port2
mov portval,ax
ret
comx: pop bx
ret
COMS ENDP
VTS PROC NEAR
jmp notimp
VTS ENDP
notimp: mov ah,prstr
mov dx,offset noimp
int dos
jmp prserr
lclini: mov trans.escchr,ctrla ; Use Control-A as escape char.
mov swchar,'/'
ret
showkey:
mov ax,offset shkmsg
mov cx,shklen
ret
; Common initialization for using serial port.
SERINI PROC NEAR
cmp portin,0 ; already inited?
jne serin1 ; yes, skip it
mov portin,1 ; remember inited
mov dx,rcvcmd
in al,dx ; read cmd register to reset mode ptr.
mov dx,trmod
mov al,mod1
out dx,al
push bx
mov bx,portval
mov si,[bx].baud
pop bx
mov al,baudtab[si]
or al,mod2
out dx,al
mov dx,wrcmd
mov al,txen+dtr+rxen+clrerr+rts
out dx,al ; enable transmit and receive
call clrbuf ; empty buffer
mov al,settrp
mov bx,chrrdy ; interrupt on character ready
mov cx,0 ; interrupt immediately
mov dx,offset serint ; handler routine
mov prtcnt,0 ; no characters in yet
push ds
mov si,cs
mov ds,si
int wbios
pop ds
or al,al
jne serin1
mov qid,bx ; preserve trap identification
serin1: ret ; We're done. [21c]
SERINI ENDP
SERRST PROC NEAR
cmp portin,0 ; already de-inited?
je serrs1 ; yes, skip this
mov portin,0
mov al,clrtrp
mov bx,qid
int wbios
serrs1: ret
SERRST ENDP
; serial interrupt handler
serint proc far
push ds
push ax
push dx
push di
mov ax,seg datas
mov ds,ax
mov di,bufin
mov dx,rcvdat
in al,dx
mov [di],al
inc di
cmp di,offset source + bufsiz
jb sernt1
mov di,offset source
sernt1: mov bufin,di
inc count
pop di
pop dx
pop ax
pop ds
ret
serint endp
; Generate a short beep.
BEEP PROC NEAR
mov dl,bell
mov ah,conout
int dos
ret
BEEP ENDP
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
term proc near
mov si,ax ; this is source
mov di,offset ourarg ; place to store arguments
mov ax,ds
mov es,ax ; address destination segment
mov cx,size termarg
rep movsb ; copy into our arg blk
term1: call prtchr
jmp short term2 ; have a char...
nop
nop
jmp short term3 ; no char, go on
term2: and al,7fh
push ax
mov dl,al
mov ah,dconio
int dos ; write out the character
pop ax
test ourarg.flgs,capt ; capturing output?
jz term3 ; no, forget it
call ourarg.captr ; else call the routine
term3: mov ah,dconio
mov dl,0ffh
int dos
or al,al
jz term1 ; no character, go on
cmp al,ourarg.escc ; escape char?
je term4 ; yes, exit
push ax ; save char
mov ah,al
call outchr ; output the character
nop
nop
nop
pop ax
test ourarg.flgs,lclecho ; echoing?
jz term1 ; no, continue loop
mov dl,al
mov ah,dconio
int dos
jmp term1 ; else echo and keep going
term4: ret
term endp
code ends
end
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 640 msxwng.asm
/bin/echo -n ' '; /bin/ls -ld msxwng.asm
fi
/bin/echo 'Extracting msxz100.asm'
sed 's/^X//' <<'//go.sysin dd *' >msxz100.asm
; Kermit system dependent module for Heath/Zenith Z100
public serini, serrst, clrbuf, outchr, coms, vts, dodel,
public ctlu, cmblnk, locate, prtchr, dobaud, clearl,
public dodisk, getbaud, beep,
public count, xofsnt, puthlp, putmod, clrmod, poscur
public sendbr, machnam, setktab, setkhlp, lclini, showkey
include msdefs.h
false equ 0
true equ 1
mntrgh equ bufsiz*3/4 ; High point = 3/4 of buffer full.
; constants used by serial port handler
BRKBIT EQU 048H ; Send-break bit.
MDMCOM1 EQU 00EFH ; Address of modem port command. [19b]
; external variables used:
; drives - # of disk drives on system
; flags - global flags as per flginfo structure defined in pcdefs
; trans - global transmission parameters, trinfo struct defined in pcdefs
; portval - pointer to current portinfo structure (currently either port1
; or port2)
; port1, port2 - portinfo structures for the corresponding ports
; global variables defined in this module:
; xofsnt, xofrcv - tell whether we saw or sent an xoff.
; setktab - keyword table for redefining keys (should contain a 0 if
; not implemented)
; setkhlp - help for setktab.
BIOS_SEG SEGMENT AT 40H ; Define segment where BIOS really is
ORG 6*3
BIOS_AUXOUT LABEL FAR ; AUX output routine
ORG 26*3
BIOS_AUXFUNC LABEL FAR ; AUX: function
ORG 27*3
BIOS_CONFUNC LABEL FAR ; CON: function
BIOS_SEG ENDS
; Function codes for BIOS_xxxFUNC
CHR_WRITE EQU 0 ; Write character
CHR_READ EQU 1 ; Read character
CHR_STATUS EQU 2 ; Get status
CHR_SFGS EQU 0 ; Get status subfunction
CHR_SFGC EQU 1 ; Get config subfunction
CHR_CONTROL EQU 3 ; Control function
CHR_CFSU EQU 0 ; Set new configuration parameters
CHR_CFCI EQU 1 ; Clear input buffer
datas segment public 'datas'
extrn drives:byte, flags:byte, trans:byte
extrn portval:word, port1:byte, port2:byte
setktab db 13
mkeyw 'F0',96h
mkeyw 'F1',97h
mkeyw 'F2',98h
mkeyw 'F3',99h
mkeyw 'F4',9ah
mkeyw 'F5',9bh
mkeyw 'F6',9ch
mkeyw 'F7',9dh
mkeyw 'F8',9eh
mkeyw 'F9',9fh
mkeyw 'F10',0a0h
mkeyw 'F11',0a1h
mkeyw 'SCAN',-1
setkhlp db cr,lf,'Keyname: f0, ... f11, "HELP" or "SCAN" follwed by '
db 'decimal scan code$'
brkval db 0 ; What to send for a break.
brkadr dw 0 ; Where to send it.
badbd db cr,lf,'Unimplemented baud rate$'
noimp db cr,lf,'Not implemented$'
machnam db 'Heath-Zenith Z-100$'
crlf db cr,lf,'$'
delstr db BS,' ',BS,'$' ; Delete string. [21d]
home db ESC,'H$'
eeolstr db ESC,'K$' ; Erase to end of line
clrstr db ESC,'E$' ; Erase entire display
enamod db ESC,'x1$' ; Enable 25th line
dismod db ESC,'y1$' ; Disable 25th line
enascan db ESC,'y?$' ; Enable scan codes
disscan db ESC,'x?$' ; Disable scan codes
begrev db ESC,'p$' ; Enter reverse video
endrev db ESC,'q$' ; Exit reverse video
lin25 db ESC,'Y8 $' ; Column 1 row 25
savcur db ESC,'j$' ; Save current cursor position
precur db ESC,'k$' ; Restore cursor to previous position
clrlin db cr,'$' ; Clear line (just the cr part).
xofsnt db 0 ; Say if we sent an XOFF.
xofrcv db 0 ; Say if we received an XOFF.
tmp db ?,'$'
temp1 dw ? ; Temporary storage.
ontab db 02H ; Two entries.
db 03H,'OFF$' ; Should be alphabetized. [19a]
dw 00H
db 02H,'ON$'
dw 01H
; this table is indexed by the baud rate definitions given in
; pcdefs. Unsupported baud rates should contain FF.
bddat label word
dw 0 ; 45.5 baud
dw 1 ; 50 baud
dw 2 ; 75 baud
dw 3 ; 110 baud
dw 4 ; 134.5 baud
dw 5 ; 150 baud
dw 6 ; 300 baud
dw 7 ; 600 baud
dw 8 ; 1200 baud
dw 9 ; 1800 baud
dw 10 ; 2000 baud
dw 11 ; 2400 baud
dw 12 ; 4800 baud
dw 13 ; 9600 baud
dw 14 ; 19200 baud
dw 15 ; 38400 baud
; storage for port configuration
cfginfo struc
cfclass db 0
cfattr db 0
cfport dw 0
cfbaud db 0
cfhshk db 0
cfbctl db 0
cfecnt db 0
cfncnt db 0
cfnchr db 0
cfres db 6 dup(?)
cfsize db 0
cfginfo ends
auxconf cfginfo <>
; variables for serial interrupt handler
count dw 0 ; Number of chars in int buffer.
ourarg termarg <>
shkbuf db 300 dup (?) ; room for definition
shkmsg db ' Scan code: '
shkmln equ $-shkmsg
shkms1 db cr,lf,' Definition: '
shkm1ln equ $-shkms1
datas ends
code segment public
extrn comnd:near, dopar:near, defkey:near
assume cs:code,ds:datas
; local initialization
lclini proc near
mov brkval,BRKBIT ; What to send for a break.
mov brkadr,MDMCOM1
mov flags.vtflg,0 ; Turn off true Heath mode (allows key macros)
ret
lclini endp
; this is called by Kermit initialization. It checks the
; number of disks on the system, sets the drives variable
; appropriately. Returns normally.
DODISK PROC NEAR
mov ah,gcurdsk ; Current disk value to AL.
int dos
mov dl,al ; Put current disk in DL.
mov ah,seldsk ; Select current disk.
int dos
mov drives,al
ret
DODISK ENDP
; show the definition of a key. The terminal argument block (which contains
; the address and length of the definition tables) is passed in ax.
; Returns a string to print in AX, length of same in CX.
; Returns normally.
showkey proc near
push es
push ax ; save the ptr
mov bx,ds
mov es,bx ; address data segment
cld
showk1: mov ah,prstr
mov dx,offset enascan ; enable scan codes
int dos
mov ah,0ch ; char input with buffer flush
mov al,7
int dos
; mov ah,chr_control
; mov al,chr_cfci ; clear input
; call bios_confunc
; mov ah,chr_read
; call bios_confunc ; read a char
push ax
mov ah,prstr
mov dx,offset disscan ; disable scan codes
int dos
pop ax
; push ax ; save the character
; call gss ; get shift state
; pop bx
mov ah,0 ; shift state to ah
; mov al,bh ; scan code to al
push ax ; remember scan code
mov di,offset shkbuf
mov si,offset shkmsg
mov cx,shkmln
rep movsb ; copy in initial message
call nout ; write out scan code
mov si,offset shkms1
mov cx,shkm1ln ; second message
rep movsb
pop ax ; get scan code back
pop bx ; and terminal arg block
mov cx,[bx].klen ; and length
jcxz showk2 ; no table, not defined
push di ; remember output ptr
mov di,[bx].ktab ; get key table
repne scasw ; search for a definition for this
mov si,di ; remember result ptr
pop di ; get output ptr back
jne showk2 ; not defined, forget it
sub si,[bx].ktab ; compute offset from beginning
sub si,2 ; minus 2 for pre-increment
add si,[bx].krpl ; get index into replacement table
mov si,[si] ; pick up replacement
mov cl,[si] ; get length
mov ch,0
inc si
rep movsb ; copy into buffer
showk2: mov ax,offset shkbuf ; this is buffer
mov cx,di
sub cx,ax ; length
pop es
ret ; and return
showkey endp
; Clear the input buffer. This throws away all the characters in the
; serial interrupt buffer. This is particularly important when
; talking to servers, since NAKs can accumulate in the buffer.
; Returns normally.
CLRBUF PROC NEAR
cli
mov ah,chr_control
mov al,chr_cfci
call bios_auxfunc
mov count,0
sti
ret
CLRBUF ENDP
; Clear to the end of the current line. Returns normally.
CLEARL PROC NEAR
mov ah,prstr
mov dx,offset eeolstr ; Erase to end of line
int dos
ret
CLEARL ENDP
; Put the char in AH to the serial port. This assumes the
; port has been initialized. Should honor xon/xoff. Skip returns on
; success, returns normally if the character cannot be written.
outchr: mov bp,portval
cmp ds:[bp].floflg,0 ; Are we doing flow control.
je outch2 ; No, just continue.
xor cx,cx ; clear counter
outch1: cmp xofrcv,true ; Are we being held?
jne outch2 ; No - it's OK to go on.
loop outch1 ; held, try for a while
mov xofrcv,false ; timed out, force it off and fall thru.
outch2: push dx ; Save register.
mov al,ah ; Parity routine works on AL.
call dopar ; Set parity appropriately.
call bios_auxout
pop dx
jmp rskp
; This routine blanks the screen. Returns normally.
CMBLNK PROC NEAR
mov ah,prstr
mov dx,offset clrstr
int dos
ret
CMBLNK ENDP
; Locate: homes the cursor. Returns normally.
LOCATE PROC NEAR
mov ah,prstr
mov dx,offset home ; Go to top left corner of screen.
int dos
LOCATE ENDP
; write a line in inverse video at the bottom of the screen...
; the line is passed in dx, terminated by a $. Returns normally.
putmod proc near
push dx ; preserve message
mov ah,prstr
mov dx,offset savcur
int dos
mov dx,offset enamod
int dos
mov dx,offset lin25
int dos
mov dx,offset begrev
int dos
pop dx ; get message back
int dos ; write it out
mov dx,offset endrev
int dos
mov dx,offset precur
int dos
ret ; and return
putmod endp
; clear the mode line written by putmod. Returns normally.
clrmod proc near
mov ah,prstr
mov dx,offset dismod
int dos
ret
clrmod endp
BEEP PROC NEAR
mov dl,07 ; ASCII BEL
mov ah,dconio
int dos ; Ring it
ret
BEEP ENDP
; put a help message on the screen. This one uses reverse video...
; pass the message in ax, terminated by a null. Returns normally.
puthlp proc near
push ax ; preserve this
mov ah,prstr
mov dx,offset crlf
int dos
pop si ; point to string again
puthl3: lodsb ; get a byte
cmp al,0 ; end of string?
je puthl4 ; yes, stop
mov dl,al
mov ah,dconio
int dos
jmp puthl3 ; and keep going
puthl4: mov ah,prstr
mov dx,offset crlf
int dos
ret
puthlp endp
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns normally.
DOBAUD PROC NEAR
mov bp,portval
mov temp1,ax ; Don't overwrite previous rate. [25]
mov ax,ds:[bp].baud ; Check if new rate is valid. [25]
mov tmp,2
mul tmp ; Get index into baud table.
mov bx,offset bddat ; Start of table.
add bx,ax
mov ax,[bx] ; The data to output to port.
cmp ax,0FFH ; Unimplemented baud rate.
jne dobd0
mov ax,temp1 ; Get back orginal value.
mov ds:[bp].baud,ax ; Leave baud rate as is.
mov ah,prstr
mov dx,offset badbd ; Give an error message.
int dos
ret
dobd0: push ax ; Save it
mov bx,ds ; Set up pointer to config info
mov es,bx ; . . .
mov bx,offset auxconf ; . . .
mov ah,chr_status
mov al,chr_sfgc ; get current config info
call bios_auxfunc
pop ax ; get baud back
mov auxconf.cfbaud,al
mov ah,chr_control ; Function is control
mov al,chr_cfsu ; Subfunction is set new config
call bios_auxfunc ; Set the configuration
ret
DOBAUD ENDP
; Get the current baud rate from the serial card and set it
; in the portinfo structure for the current port. Returns normally.
; This is used during initialization.
GETBAUD PROC NEAR
mov bx,ds
mov es,bx
mov bx,offset auxconf
mov ah,chr_status
mov al,chr_sfgc ; Status function get config info
call bios_auxfunc
mov ch,0
mov cl,auxconf.cfbaud
mov bp,portval
mov ds:[bp].baud,cx
ret
GETBAUD ENDP
; skip returns if no character available at port,
; otherwise returns with char in al, # of chars in buffer in dx.
PRTCHR PROC NEAR
call chkxon ; see if we need to xon
push bx
mov ah,chr_status
mov al,chr_sfgs ; Status function get status
call bios_auxfunc
cmp bl,0
jnz prtch2
pop bx
jmp rskp ; No data - check console.
prtch2: mov dh,0
mov dl,bl ; Place # of chars in dx
mov ah,chr_read
call bios_auxfunc
dec dl ; Decrement number of chars
mov count,dx ; Save count for posterity
pop bx
ret
PRTCHR ENDP
; local routine to see if we have to transmit an xon
chkxon proc near
push bx
mov bx,portval
cmp [bx].floflg,0 ; doing flow control?
je chkxo1 ; no, skip all this
cmp xofsnt,false ; have we sent an xoff?
je chkxo1 ; no, forget it
cmp count,mntrgh ; below trigger?
jae chkxo1 ; no, forget it
mov ax,[bx].flowc ; ah gets xon
call outchr ; send it
nop
nop
nop ; in case it skips
mov xofsnt,false ; remember we've sent the xon.
chkxo1: pop bx ; restore register
ret ; and return
chkxon endp
; Send a break out the current serial port. Returns normally.
SENDBR PROC NEAR
push cx
push dx
push ax
xor cx,cx ; Clear loop counter.
mov dx,brkadr ; Port address. [19b]
in al,dx ; Get current setting.
or al,brkval ; Set send-break bit(s).
out dx,al ; Start the break.
pause: loop pause ; Wait a while.
xor al,brkval ; Clear send-break bit(s).
out dx,al ; Stop the break.
pop ax
pop dx
pop cx
ret ; And return.
SENDBR ENDP
; Position the cursor according to contents of DX:
; DH contains row, DL contains column. Returns normally.
POSCUR PROC NEAR
push dx
mov ah,CONOUT
mov dl,ESC
int dos
mov dl,'Y'
int dos
pop dx
push dx
mov dl,dh
add dl,' '
int dos
pop dx
add dl,' '
int dos
ret
POSCUR ENDP
; Delete a character from the terminal. This works by printing
; backspaces and spaces. Returns normally.
DODEL PROC NEAR
mov ah,prstr
mov dx,offset delstr ; Erase weird character.
int dos
ret
DODEL ENDP
; Move the cursor to the left margin, then clear to end of line.
; Returns normally.
CTLU PROC NEAR
mov ah,prstr
mov dx,offset clrlin
int dos
call clearl
ret
CTLU ENDP
; set the current port.
COMS PROC NEAR
jmp notimp
COMS ENDP
; Set heath emulation on/off.
VTS PROC NEAR
mov dx,offset ontab
mov bx,0
mov ah,cmkey
call comnd
jmp r
push bx
mov ah,cmcfm
call comnd ; Get a confirm.
jmp vt0 ; didn't get a confirm.
nop
pop bx
mov flags.vtflg,bl ; Set the Heath emulation flag
ret
vt0: pop bx
ret
VTS ENDP
notimp: mov ah,prstr
mov dx,offset noimp
int dos
jmp rskp
; initialization for using serial port. This routine performs
; any initialization necessary for using the serial port, including
; setting up interrupt routines, setting buffer pointers, etc.
; Doing this twice in a row should be harmless (this version checks
; a flag and returns if initialization has already been done).
; SERRST below should restore any interrupt vectors that this changes.
; Returns normally.
SERINI PROC NEAR
ret ; We're done.
SERINI ENDP
; Reset the serial port. This is the opposite of serini. Calling
; this twice without intervening calls to serini should be harmless.
; Returns normally.
SERRST PROC NEAR
ret ; All done.
SERRST ENDP
; put the number in ax into the buffer pointed to by di. Di is updated
nout proc near
mov dx,0 ; high order is always 0.
mov bx,10
div bx ; divide to get digit
push dx ; save remainder digit
or ax,ax ; test quotient
jz nout1 ; zero, no more of number
call nout ; else call for rest of number
nout1: pop ax ; get digit back
add al,'0' ; make printable
stosb ; drop it off
ret ; and return
nout endp
; Jumping to this location is like retskp. It assumes the instruction
; after the call is a jmp addr.
RSKP PROC NEAR
pop bp
add bp,3
push bp
ret
RSKP ENDP
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
code ends
end
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 640 msxz100.asm
/bin/echo -n ' '; /bin/ls -ld msxz100.asm
fi
/bin/echo 'Extracting msyibm.asm'
sed 's/^X//' <<'//go.sysin dd *' >msyibm.asm
title term
public term, gss ; entry points
include msdefs.h
; some character definitions
chesc equ 27
bel equ 7
print_out equ 05h ; dos function to print to printer
pbout equ 02h ; dos function to print a character
prscan equ 72h ; print-screen scan code...
upscan equ 49h ; up page
dnscan equ 51h ; down page
ctlup equ 84h ; ctl-up page
ctldn equ 76h ; ctl-down page
homscn equ 47h ; home screen
endscn equ 4fh ; end of screen
screen equ 10h ; bios screen call
kb equ 16h ; keyboard interrupt
alt_shift equ 8H ; alt shift key down
ctl_shift equ 4H ; ctl key down
left_shift equ 2H ; left shift key down
right_shift equ 1H ; right shift key down
timer equ 40h ; timer port
bel_prt equ 61h ; speaker control
crt_status equ 3dah ; crt status port
disp_enb equ 8 ; display enable bit
uparr equ 48h ; scan codes for arrow keys
dnarr equ 50h
lftarr equ 4bh
rgtarr equ 4dh
modfrm struc ; format of mode line
db 'Esc chr: '
m_echr db 2 dup (?)
db ', Port: '
m_prt db 1 dup (?)
db ', Speed: '
m_baud db 4 dup (?)
db ', Parity: '
m_par db 4 dup (?)
db ', Echo: '
m_echo db 3 dup (?)
db ', Type '
m_hlp db 2 dup (?)
db '? for Help'
modfrm ends
datas segment public 'datas'
waste db 100h dup (?) ;*** need this junk because assembler
;*** generates non-relocatable offsets
;*** for things like
;*** "sub di,offset foo"
;*** if offset foo < 100H
; stuff for screen routines
flags db ? ; status flags...
flags1 db 0 ; internal flags.
prtscr equ 80h ; print screen pressed
lnwrap equ 40h ; line wrap enabled.
inited equ 08h ; been here before...
cursor dw ?
esc_ch db ?
argadr dw ? ; address of arg blk
ckeys db 0,prscan,dnscan,upscan,endscn,homscn,ctlup,ctldn
db uparr,dnarr,lftarr,rgtarr
lckeys equ $-ckeys
; ckacts must parallel ckeys above...
ckacts dw trnbrk,trnprs,upwpg,dnwpg,endwnd,homwnd,dnwind,upwind
dw trnupw,trndnw,trnlfw,trnrgw
uptrn db esc,'A'
dntrn db esc,'B'
rgtrn db esc,'C'
lftrn db esc,'D'
spctab db chesc,cr,lf,bs,tab,bel
lspctab equ $-spctab
spcjmp dw outesc,outcr,outlf,outbs,outtab,outbel ; must match spctab
esctab db 'YABCDEFGHIJKLM'
db 'NOZ@[pq<vw'
lesctab equ $-esctab
; escjmp must parallel esctab above
escjmp dw movcur,curup,curdwn,currt,outbs,clrscr,outign,outign,curhom
dw revind,clreow,clreol,inslin,dellin,delchr,noins
dw vtident,entins,doansi
dw invvid,nrmvid,outign,dowrap,nowrap
vtidstr db chesc,'/K'
lvtidst equ $-vtidstr
coord dw ?
insmod db ?
wcoord dw ?
ttstate dw outtt0
curattr db ? ; current attribute
ansarg db ? ; ansi argument value
igncnt db ? ; # of chars to ignore
beldiv dw 2dch ; 550 hz?
crt_mode db ?
crt_cols db ?
crt_lins db ?
low_rgt dw ? ; lower right corner of window
; key redefinitions
ktrntab dw ? ; address of translation table
krpltab dw ? ; address of replacement table
tmptab db 0eh,3bh ; scan code for bs, f1
ktlen dw ?
modbuf modfrm <> ; mode line buffer
; routine to call for captured output
captrtn dw ?
; some static data for mode line
unkbaud db 'Unk ' ; must be 4 chars...
baudn db '45.5'
db ' 50'
db ' 75'
db ' 110'
db ' 135'
db ' 150'
db ' 300'
db ' 600'
db '1200'
db '1800'
db '2000'
db '2400'
db '4800'
db '9600'
baudnsiz equ 14 ; # of baud rates known (tbl size / 4)
parnams db 'Even'
db 'Mark'
db 'None'
db 'Odd ' ; must be 4 chars
db 'Spc '
offmsg db 'Off'
onmsg db 'On '
lclmsg db 'Lcl'
remmsg db 'Rem'
; storage for multi-window stuff
swidth equ 80
slen equ 24
npgs equ 5 ; # of pages on each side
bsize equ swidth*slen*npgs*2
scrsav dw swidth*slen dup (0700H) ; a blank screen
; circular buffer. To work properly, the buffer size should be an exact
; multiple of swidth*2
cbuf struc
pp dw ? ; place ptr in buffer
bend dw ? ; end of buffer
orig dw ? ; buffer origin
lcnt dw 0 ; # of lines in buffer.
cbuf ends
topbuf db bsize dup (?)
botbuf db bsize dup (?) ; top and bottom windows
tlbuf db swidth*2 dup (?)
blbuf db swidth*2 dup (?)
twnd cbuf <topbuf,topbuf+bsize-1,topbuf,0>
bwnd cbuf <botbuf,botbuf+bsize-1,botbuf,0>
portno db ?
prton db 'Printer: on'
prtnlen equ $-prton
prtoff db 'Printer: off'
prtflen equ $-prtoff
datas ends
code segment public ; code segment
extrn prtchr:near,outchr:near,sendbr:near
assume cs:code,ds:datas,es:datas
scrini proc near ; init screen stuff
mov ah,15 ; read video state...
int screen
mov crt_mode,al ; save crt mode
cmp ah,crt_cols ; is real # of cols < passed?
jge scrin1 ; no
mov crt_cols,ah ; yes, save # of cols
scrin1: mov dl,crt_cols ; # of cols again
mov dh,crt_lins ; and # of rows
dec dl
dec dh
mov low_rgt,dx ; save away window address
mov insmod,0 ; not in insert mode
mov dx,cursor ; assume old cursor
test flags1,inited ; have we been here before?
jnz scrin4 ; yes, use old cursor
mov curattr,07 ; else set nice screen attribute
mov ttstate,offset outtt0 ; normal screen state
mov ah,3 ; figure out where cursor is
xor bh,bh ; page 0
int screen ; read cursor position
cmp dh,crt_lins ; past logical end of screen?
jb scrin2 ; no, keep going
mov dh,byte ptr low_rgt+1 ; yes, just use lower right corner
scrin2: cmp dl,crt_cols ; maybe past right margin
jb scrin3 ; no, use the way it is
mov dl,byte ptr low_rgt
scrin3: mov cursor,dx ; init cursor
scrin4: mov ah,2
xor bh,bh
int screen ; set cursor in case it moved
ret
scrini endp
argini proc near ; read passed arguments
mov bx,argadr ; base of argument block
mov al,[bx].flgs ; get flags
and al,capt+emheath+havtt+trnctl+lclecho+modoff
mov flags,al ; mask for allowable and save
and flags1,not (prtscr) ; these are allowable
; (others remain).
mov al,[bx].prt
cmp al,portno ; using same port?
je argin1 ; yes, go on
and flags1,not inited ; else re-init stuff
argin1: mov portno,al ; update port number
mov al,[bx].cols
mov crt_cols,al
mov al,[bx].rows
mov crt_lins,al ; init # of rows and cols
mov ax,[bx].captr
mov captrtn,ax ; buffer capture routine
mov ax,[bx].belld
mov beldiv,ax ; bell divisor
mov ax,[bx].klen
mov ktlen,ax ; length of key redef tbl
mov ax,[bx].ktab
mov ktrntab,ax ; save key translation table
mov ax,[bx].krpl
mov krpltab,ax
mov al,[bx].escc
mov esc_ch,al
ret ; that's it
argini endp
modlin proc near ; turn on mode line
mov al,esc_ch
mov modbuf.m_echr,' ' ; first char is initial space
mov modbuf.m_hlp,' ' ; goes here too.
cmp al,32 ; printable?
jnb modl1 ; yes, keep going
add al,40h ; made printable
mov modbuf.m_echr,'^' ; note control char
mov modbuf.m_hlp,'^'
modl1: mov modbuf.m_echr+1,al ; fill in character
mov modbuf.m_hlp+1,al
mov bx,argadr ; get argument block
mov al,[bx].baudb ; get baud bits
mov si,offset unkbaud ; assume unknown baud
cmp al,baudnsiz ; too big?
jnb modl2 ; yes, use default
mov cl,2 ; each is 4 bytes long
shl al,cl
mov ah,0
add ax,offset baudn
mov si,ax
modl2: mov cx,size m_baud ; length of baud space
mov di,offset modbuf.m_baud
rep movsb ; copy in baud rate
mov al,[bx].parity ; get parity code
mov cl,2 ; each is 4 bytes long...
shl al,cl
mov ah,0
add ax,offset parnams ; names of parity settings
mov si,ax
mov cx,4 ; each is 4 long
mov di,offset modbuf.m_par
rep movsb
mov si,offset lclmsg ; assume remote echoing
test flags,lclecho ; echoing?
jz modl4 ; no, keep going
mov si,offset remmsg
modl4: mov cx,3 ; size of on/off
mov di,offset modbuf.m_echo
rep movsb
mov al,'1'
cmp portno,1 ; port 1?
je modl5 ; yes, keep going
mov al,'2'
modl5: mov modbuf.m_prt,al ; fill in port number
mov cx,size modfrm ; this is size of mode line
mov si,offset modbuf ; mode line image
; alternate entry to write an alternate mode line
modwrt: push cx
push si ; save mode line and size
mov dx,24 * 100h ; 25th line for mode line
push word ptr curattr ; save current attributes
mov curattr,70h ; want inverse video
call clreol ; clear to end of line...
pop word ptr curattr ; restore attributes
mov dx,24 * 100h
mov bh,0
mov ah,2 ; set cursor position
int screen
pop si
pop cx ; restore these
modl6: lodsb ; get a byte
mov ah,14 ; write to terminal
mov bh,0 ; page 0
int screen
loop modl6 ; write out entire mode line
mov dx,cursor
mov ah,2
mov bh,0
int screen ; put cursor back where it belongs
ret ; and return
modlin endp
clrmod proc near ; clear mode line
mov ax,600h ; blank window
mov cx,24 * 100h ; beginning of window
mov dx,24 * 100h + 79 ; end of window
mov bh,07 ; nice attribute
int screen ; clear mode line
ret ; and return
clrmod endp
term proc near ; terminal emulator entry point
mov argadr,ax ; save argument ptr
push es ; save caller's extra segment address
mov ax,seg datas
mov es,ax
call argini ; init options from arg address
call scrini ; init screen stuff
test flags1,inited ; have we run yet?
jz term1 ; no, forget this part
call restscr ; restore screen
term1: or flags1,inited ; remember we've run already.
call clrmod ; empty mode line
test flags,modoff ; is mode line disabled?
jnz lp ; yes, skip it
call modlin ; turn on mode line
lp: call portchr ; char at port?
jnc chkinp ; no, keep going
call outtty ; print on terminal
chkinp: mov ah,1
int kb
jz lp ; nothing available...
xor ah,ah
int kb ; get the char from the buffer
push ax ; save character temporarily
call gss ; get shift state into al
mov bl,al ; save shift state
pop ax
cmp al,esc_ch ; escape character?
je quit ; yes, stop here
call trnout ; translate if nec., output to prt
jmp chkinp ; and keep going
quit: call clrmod ; erase mode line
call savescr ; save screen
mov al,flags
mov bx,argadr
mov [bx].flgs,al ; update flags in arg block
pop es ; restore segment register
ret ; and return to caller
term endp
; get shift state into al. We only care about shift, ctl, and alt keys.
; right shift is collapsed into left shift.
gss proc near
mov ah,2
int kb ; get current shift state
mov bl,al ; copy for a moment
and bl,right_shift ; mask out all but right shift
shl bl,1 ; move right shift to left shift pos
or al,bl ; collapse shift bits
and al,(left_shift + alt_shift + ctl_shift)
ret
gss endp
; save the screen so we can restore it
; maybe save cursor also.
savescr proc near
push ds
mov si,0
mov di,offset scrsav ; place to put screen
mov cx,80*24 ; # of words on screen
call scrseg
push ax ; save screen segment
call scrwait ; wait for screen to be ready
pop ds ; address screen
rep movsw ; save the screen
pop ds ; restore this
ret ; and return
savescr endp
; restore screen from scrsav buffer
restscr proc near
push es
mov si,offset scrsav ; source
mov di,0
mov cx,80*24
call scrseg
mov es,ax
call scrwait
rep movsw ; restore it
pop es
ret
restscr endp
; send the character in al out to the serial port
; handle echoing also...
outprt proc near
test flags,lclecho ; echoing?
jz outpr1 ; no, forget it
push ax ; save char
call outtty ; print it
pop ax ; restore
outpr1: mov ah,al ; this is where outchr expects it
call outchr ; output to the port
nop
nop
nop ; skip returns...
ret
outprt endp
; returns with carry on if a character is available
portchr proc near
call prtchr ; character at port?
jmp short portc1 ; yes, go handle
nop ; skip return is stupid...
clc ; no carry -> no character
ret ; and return...
portc1: and al,7fh ; we don't worry about parity here
stc ; have a character
ret ; and return
portchr endp
; translate the scan code in ah according to the translate table
; given in ktrntab/krpltab, output to port. If no translation,
; use ascii char in al. (should probably include shift state
; somewhere). Shift state is in bl.
trnout proc near
cmp ah,4eh ;*** plus key thing?
je trnmod ; yes, go toggle mode line
trnou1: test flags,havtt ; translate table given?
jz trnou3 ; no, just output character
push ax ; save original value
mov al,ah ; put scan code into ah
mov ah,bl ; shift state into top half.
mov di,ktrntab ; pick up translate tbl
mov cx,ktlen ; length of tbl
repne scasw ; look for our key
pop ax ; recover character
jne trnou3 ; not found, forget it
sub di,ktrntab ; get index into tbl
sub di,2 ; (minus 2 for pre-increment)
mov bx,krpltab ; get replacement table
mov si,[bx][di] ; and addr of replacement
mov cl,[si] ; get first byte (length)
xor ch,ch ; clear high-order byte
inc si ; point to translation string
trnou2: lodsb ; get a byte
push si
push cx ; save important registers
call outprt ; send to port
pop cx
pop si
loop trnou2 ; send all chars
ret ; and return
trnou3: cmp al,0 ; is it a special code?
jne trnou4 ; no, don't do this
mov al,ah ; get scan code
mov cx,lckeys ; length of table
mov di,offset ckeys ; table address
repne scasb
mov al,0 ; ascii code was 0...
jne trnou4 ; not found, keep going
sub di,offset ckeys+1 ; get table offset
shl di,1 ; shift for word offset
jmp ckacts[di] ; jump to appropriate routine
trnou4: call outprt ; just output single char
ret ; and return
trnmod: test flags,modoff ; mode line already off?
jnz trnm1 ; yes, go turn on
call clrmod ; no, clear mode line here
or flags,modoff ; turn on flag
ret ; and return
trnm1: call modlin ; turn on mode line
and flags,not modoff ; clear flag
ret ; and return
trnbrk: mov ah,dconio
mov dl,0ffH
int dos ; read the bogus ^C DOS gets.
call sendbr
ret
trnprs: xor flags1,prtscr ; flip the flag
and flags,not modoff ; turn on mode line
mov si,offset prton
mov cx,prtnlen
test flags1,prtscr ; did it go on?
jnz trnpr1 ; yes, say so
mov si,offset prtoff
mov cx,prtflen
trnpr1: call modwrt ; write into mode line
ret ; and return
; common entry for arrow keys
trnarr: mov cx,2 ; length is always 2
jmp trnou2 ; go send definition
trnupw: mov si,offset uptrn
jmp trnarr
trndnw: mov si,offset dntrn
jmp trnarr
trnlfw: mov si,offset lftrn
jmp trnarr
trnrgw: mov si,offset rgtrn
jmp trnarr
trnout endp
; move viewing window up (screen moves down).
; alternate entry upwin2 doesn't beep if invalid.
upwind proc near
mov ax,offset tlbuf ; place to put line temporarily
mov bx,offset twnd ; where to get lines from
call getcirc ; try to get a line
jnc upwin3 ; have a line, go show it
call outbel ; else ring bel
ret ; and return
upwin2: mov ax,offset tlbuf
mov bx,offset twnd
call getcirc
jnc upwin3
ret ; this just rets if no line avail.
upwin3: mov ax,offset blbuf ; place for bottom line
call getbot ; fetch bottom line
mov ax,offset blbuf
mov bx,offset bwnd
call putcirc ; save in circular buffer
mov ax,701h ; scroll down one line
xor cx,cx ; from top
mov dx,low_rgt ; to bottom
mov bh,curattr
int screen ; scroll it down
mov di,0 ; offset for destination
mov si,offset tlbuf ; where to get line from
mov cx,swidth ; length of line
push es
call scrseg
push ax
call scrwait
pop es
rep movsw ; copy the line in
pop es ; restore this
ret ; and return
upwind endp
; move viewing window down a line (screen scrolls up)
; entry dwin2 does same w/out checking to see if scroll is legal
dnwind proc near
mov ax,offset blbuf ; place to put line temporarily
mov bx,offset bwnd ; where to get lines from
call getcirc ; try to get a line
jnc dnwin3 ; have a line, go show it
call outbel ; else ring bel
ret ; and return
dnwin2: mov ax,offset blbuf
mov bx,offset bwnd
call getcirc
jnc dnwin3
ret ; this just rets if no line avail.
dnwin3: call scrprep ; save top line
mov ax,601h ; scroll up one line
xor cx,cx ; from top
mov dx,low_rgt ; to bottom
mov bh,curattr
int screen ; scroll it down
mov dx,low_rgt
mov dl,0 ; get addr of last line
call scrloc
mov di,ax ; this is offset in dest
mov si,offset blbuf ; where to get line from
mov cx,swidth ; length of line
push es
call scrseg
push ax
call scrwait
pop es
rep movsw ; copy the line in
pop es ; restore this
ret ; and return
dnwind endp
; move viewing window down as much as possible...
endwnd proc near
mov cx,1000 ; large number of lines
jmp dnwp1 ; and enter dwnpg
endwnd endp
; scroll viewing window down (contents move up) crt_lins times...
dnwpg proc near
mov cl,crt_lins
mov ch,0
dnwp1: push cx ; save this
call dnwin2
pop cx
loop dnwp1
ret ; and return
dnwpg endp
; home viewing window
homwnd proc near
mov cx,1000 ; large # of lines
jmp upwp1 ; join upwpg
homwnd endp
; scroll viewing window up (screen moves down) a page
upwpg proc near
mov cl,crt_lins
mov ch,0
upwp1: push cx
call upwin2
pop cx
loop upwp1
ret ; and return
upwpg endp
; get the bottom line into the buffer pointed to by ax.
getbot proc near
push ds
mov di,ax ; save dest
mov cx,swidth
mov dx,low_rgt
mov dl,0
call scrloc
mov si,ax
call scrseg
push ax
call scrwait
pop ds
rep movsw
pop ds
ret
getbot endp
; put a line into the circular buffer. Pass the buffer structure
; in bx, the pointer to the line in ax.
putcirc proc near
push si
push di
push cx
push dx
mov di,[bx].pp ; pick up buffer ptr
add di,2*swidth ; increment to next avail slot
cmp di,[bx].bend ; past end?
jb putci1 ; no, leave alone
mov di,[bx].orig ; else start at beginning
putci1: mov [bx].pp,di ; update ptr
mov si,ax ; this is source
mov cx,swidth
rep movsw ; copy into buffer
cmp [bx].lcnt,npgs*slen ; can we increment it?
jae putci2 ; no, keep going
inc [bx].lcnt ; else count this line
putci2: pop dx
pop cx
pop di
pop si ; restore registers
ret
putcirc endp
; get a line from the circular buffer, removing it from the buffer.
; returns with carry on if the buffer is empty.
; pass the buffer structure in bx, the buffer to copy the line into
; in ax.
getcirc proc near
push si
push di
push cx
push dx
cmp [bx].lcnt,0 ; any lines in buffer?
jne getci1 ; yes, ok to take one out.
stc ; else set carry
jmp short getcir3 ; and return
getci1: mov si,[bx].pp ; this is source
mov di,ax ; this is dest
mov cx,swidth ; # of chars to copy
rep movsw
mov si,[bx].pp ; get ptr again
sub si,2*swidth ; move back
cmp si,[bx].orig ; compare to origin
jae getcir2 ; still in range, continue
mov si,[bx].bend ; else use end of buffer
sub si,2*swidth-1 ; minus length of a piece
getcir2:mov [bx].pp,si ; update ptr
dec [bx].lcnt ; decrement # of lines in buffer
clc ; make sure no carry
getcir3:pop dx
pop cx
pop di
pop si
ret
getcirc endp
; call before scrolling to save top line...
scrprep proc near
push ds
mov si,0 ; offset of top line
mov cx,swidth ; length of line
mov di,offset tlbuf ; place to put line temporarily
call scrseg
push ax
call scrwait
pop ds
rep movsw ; copy the line
pop ds ; restore this
mov ax,offset tlbuf
mov bx,offset twnd ; this is where it goes
call putcirc ; put into buffer
ret ; and return
scrprep endp
; put the character in al to the screen
outtty proc near
test flags,capt ; capturing output?
jz outnoc ; no, forget this part
push ax ; save char
call captrtn ; give it captured character
pop ax ; restore character and keep going
outnoc: test flags1,prtscr ; should we be printing?
jz outnop ; no, keep going
push ax
mov ah,print_out
mov dl,al ; put character here for dos...
int dos
pop ax
outnop: test flags,emheath ; emulating heath?
jnz outnop1 ; yup, go do something smart
mov dl,al
mov ah,pbout
int dos ; else let dos print char
ret ; and return
outnop1:mov dx,cursor ; these may need cursor...
jmp ttstate ; jump according to current state
outtt0:
cmp al,32 ; special character?
jb outtt1 ; yes, handle specially...
cmp insmod,0 ; in insert mode?
je outnrm ; no, output normal
push ax ; save character
call inschr ; insert a character
pop ax
outnrm: xor bh,bh ; current page
mov cx,1 ; only one char
mov bl,curattr ; with current attribute
mov ah,9
int screen ; put onto screen
mov dx,cursor ; get cursor pos
currt: inc dl ; bump col
cmp dl,crt_cols ; see if in range
jb setcur ; in range, go set cursor
test flags1,lnwrap ; in wrap mode?
jz outign ; no, just return w/out updating cursor
xor dl,dl
inc dh ; handle wrap
setcur: cmp dh,crt_lins
jb setc1 ; not off end, keep going
push dx ; save row/col
call scrprep ; save top line in window buf
mov ax,0601h ; scroll up one line
xor cx,cx ; from 0,0
mov dx,low_rgt ; to 24,80
mov bh,curattr ; nice attribute
int screen ; do the scroll
pop dx
mov dh,crt_lins ; go to bottom line again...
dec dh
setc1: xor bh,bh ; page is 0
mov cursor,dx ; save cursor pos
mov ah,2
int screen ; set cursor
outign: ret ; and return
; special character (in al)
outtt1: mov di,offset spctab ; special char table
mov cx,lspctab ; length of tbl
repne scasb ; look for char in tbl
jz outtt2 ; found, go do something with it
test flags,trnctl ; are we allowed to print carets?
jz outign ; no, just ignore it.
push ax ; save char
mov al,'^'
call outtty ; print caret
pop ax
add al,'A'-1 ; make printable
jmp outtty ; print, then return
outtt2: mov dx,cursor ; might need cursor pos
sub di,offset spctab+1 ; get index of char
shl di,1 ; double for word offset
jmp spcjmp[di] ; and go handle
; special char routines. cursor is in dx, char in al
outlf: inc dh ; bump row
jmp setcur
outcr: xor dl,dl ; set col to 0
jmp setcur
outbs: or dl,dl
jle setcur ; col 0, can't back up
dec dl ; back up col
jmp setcur ; and use if reasonable
outtab: mov dl,byte ptr cursor ; get initial column
outta1: mov dh,dl ; save column ptr
push dx
mov al,' ' ; output a space
call outtty ; convenient, huh?
pop dx
mov dl,byte ptr cursor
cmp dh,dl ; is it moving?
je outta2 ; no, forget this
test dl,7 ; is it a multiple of 8?
jnz outta1 ; no, keep going
outta2: ret ; else return
; stolen from bios
outbel: mov al,10110110b ; timer initialization
out timer+3,al
mov ax,beldiv ; bel divisor
out timer+2,al
mov al,ah
out timer+2,al ; output divisor
in al,bel_prt
mov ah,al ; remember original value
or al,3 ; turn speaker on
out bel_prt,al
mov cx,8888h
outbe1: loop outbe1 ; wait a while
mov al,ah
out bel_prt,al ; turn bell off
ret ; and return
outesc: mov ttstate,offset escseq ; expect escape sequence.
ret ; and return
; escape-char handling routines
escseq: mov ttstate,offset outtt0 ; put state back to normal
mov di,offset esctab ; escape char tbl
mov cx,lesctab ; length of tbl
repne scasb ; look for it in tbl
jz escsq1 ; found, go use it
jmp outtty ; not there, just print it
escsq1: sub di,offset esctab+1 ; get offset into tbl
shl di,1 ; convert to word offset
jmp escjmp[di] ; and go dispatch on it
; escape dispatch routines
revind: cmp dh,0
jle revin1
dec dh ; back up a row
jmp setcur ; and go set cursor
revin1: push dx ; save cursor pos
mov ax,701h ; scroll down one line
xor cx,cx ; from top
mov dx,low_rgt ; to bottom
mov bh,curattr
int screen ; scroll it down
pop dx ; restore cursor.
mov dh,0 ; set row back to 0
jmp setcur
curup: cmp dh,0 ; w/in range?
jle curu1 ; no, skip this
dec dh ; else back up
curu1: jmp setcur ; and go set position
curdwn: inc dh
jmp setcur ; increment row (setcur can scroll!)
; currt is above
clrscr: call curhom ; go home cursor
jmp clreow ; then clear to end of window
curhom: xor dx,dx ; move to 0,0
jmp setcur
clreow: cmp dl,0 ; at beginning of line?
jz clrw1 ; yes, skip this part...
push dx ; remember cursor pos
call clreol ; clear to end of this line
pop dx
inc dh ; bump row
xor dl,dl ; start from col 0
clrw1: cmp dh,crt_lins ; last line on screen
jnb clrw2 ; if not in range, forget it
mov ax,700h ; clear whole window
mov cx,dx ; this is beginning
mov dx,low_rgt
; mov dx,174fh ; this is lower right corner
mov bh,curattr ; default attribute
int screen ; go clear it
clrw2: ret ; and return
clreol: push es
mov cl,crt_cols ; last col + 1
sub cl,dl ; this is # of chars to move
xor ch,ch
jcxz clrl1
call scrloc ; compute screen location (to ax)
mov di,ax
call scrseg
mov es,ax ; address screen segment
call scrwait ; wait for retrace
mov ah,curattr ; current attribute
mov al,' ' ; fill char
rep stosw ; fill line with spaces
clrl1: pop es
ret ; and return
inslin: mov al,1 ; scroll one line
; alternate entry if inserting more then one line
inslin1:mov ch,dh ; start at current row
xor cl,cl ; column 0
mov dx,low_rgt
; mov dx,174fh ; to bottom of screen
mov ah,7h ; scroll down.
mov bh,curattr ; attribute
int screen
ret
dellin: mov al,1 ; scroll 1 line
; alternate entry if deleting more than one line
dellin1:mov ch,dh ; start at current row
xor cl,cl ; column 0
mov dx,low_rgt
; mov dx,174fh ; to bottom of screen
mov ah,6h ; scroll up.
mov bh,curattr ; attribute
int screen
ret
delchr: push ds
push es
pushf ; these may get changed...
mov cl,crt_cols
dec cl
sub cl,dl ; from what we're fiddling)
xor ch,ch
jcxz delch1 ; none to move, forget it
call scrloc ; compute location
mov di,ax
mov si,ax
add si,2 ; source is next position over
call scrseg ; pick up screen segment
push ax ; put screen segment onto stack
mov es,ax ; and in destination segment
call scrwait ; wait for retrace
pop ds ; address screen segment
rep movsw ; delete it
mov byte ptr [di],' ' ; kill char at end of line
delch1: popf
pop es
pop ds
ret
inschr: push ds
push es ; save these as well
pushf ; might as well save flags...
mov dx,cursor ; this is place to do it
mov cl,crt_cols
dec cl
; mov cl,79 ; this is last col to move, +1 for length
sub cl,dl ; compute distance to end
xor ch,ch ; clear top half of offset
jcxz insch1 ; nothing to move...
mov dl,crt_cols
sub dl,2 ; last col to move
; mov dl,78 ; this is address of last col to move
call scrloc ; compute pos
mov si,ax
mov di,ax
add di,2 ; destination is one byte over...
std ; remember to move us backwards
call scrseg ; find screen segment
mov es,ax
push ax ; save screen seg on stack
call scrwait ; wait until save to write
pop ds ; address screen segment
rep movsw ; move each char and attribute
insch1: popf
pop es
pop ds
ret ; and return
noins: mov insmod,0 ; turn off insert mode
ret ; and return
movcur: mov wcoord,2 ; want two coordinates...
mov ttstate,offset getcoord
ret ; and return
vtident: mov si,offset vtidstr
mov cx,lvtidst
vtid1: lodsb ; get a byte from the string
push si ; have to save from outprt
push cx
call outprt ; send to serial port
pop cx
pop si
loop vtid1 ; go thru all chars
ret ; and return
entins: mov insmod,0ffh ; enter insert mode...
ret ; and return
doansi: mov ansarg,0 ; ansi argument is 0 (default)
mov ttstate,offset getaarg ; state is get ansi argument
ret
getaarg:cmp al,'0'
jb getaa1 ; in range for digit?
cmp al,'9'
ja getaa1
sub al,'0' ; convert to binary
mov dl,al ; tuck away
mov al,ansarg
mov dh,10
mul dh ; shift sum
add al,dl ; add in this digit (what about ovfl?)
mov ansarg,al
ret ; and return
getaa1: cmp al,'?' ; the dreaded question mark?
jne getaa2
mov ttstate,offset ignn ; we ignore these...
mov igncnt,2 ; this is how many chars come after him
ret
getaa2: mov ttstate,offset outtt0 ; reset state
mov dx,cursor ; this needs cursor position
mov bl,ansarg
xchg al,bl ; put argument in nice place
cmp bl,'L' ; insert line?
jne getaa3
jmp inslin1 ; and go do it
getaa3: cmp bl,'M' ; maybe delete line?
jne getaa4
jmp dellin1
getaa4: ret ; ignore.
invvid: mov curattr,70h ; attribute for inverse video
ret
nrmvid: mov curattr,07h ; attribute for normal video
ret
dowrap: or flags1,lnwrap ; turn on wrap mode
ret ; and return
nowrap: and flags1,not lnwrap ; turn off wrap mode
ret ; and return
; get a coordinate.
getcoord:
sub al,32 ; coordinates offset by 32
mov si,wcoord
dec si
mov byte ptr coord[si],al ; fill in appropriate coordinate
mov wcoord,si ; update flag
jnz getco1 ; more needed, can't do anything yet
mov ttstate,offset outtt0 ; reset state
mov dx,coord ; get coordinates
jmp setcur ; and go jump there
getco1: ret
; ignore following igncnt characters
ignn: dec igncnt ; decrement count
jnz ignn1
mov ttstate,offset outtt0 ; put state back to normal if done
ignn1: ret
outtty endp
; computes screen location to ax, given row and col in dx.
; trashes ax,bx
scrloc proc near
mov al,dh ; get row
mov bl,crt_cols ;** row size
mul bl ; multiply by row size
xor dh,dh ; clear col
add ax,dx ; this is current position
sal ax,1 ; double for attributes
ret
scrloc endp
; puts current screen segment in ax
scrseg proc near
mov ax,0b000h ; assume bw for now
cmp crt_mode,7 ; 7 is bw (***)
je scrse1
mov ax,0b800h ; color card
scrse1: ret
scrseg endp
; wait for retrace so can write to screen memory
scrwait proc near
cmp crt_mode,7 ; bw mode?
je scrwa3 ; yes, no waiting
push dx
mov dx,crt_status
scrwa1: in al,dx
test al,disp_enb ; display enable?
jnz scrwa1 ; yes, keep waiting
scrwa2: in al,dx
test al,disp_enb ; now wait for it to go off
jz scrwa2 ; so can have whole cycle
pop dx
scrwa3: ret ; that was easy...
scrwait endp
code ends
if1
%out [End of pass 1]
else
%out [End of assembly]
endif
end
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 640 msyibm.asm
/bin/echo -n ' '; /bin/ls -ld msyibm.asm
fi
/bin/echo 'Extracting msyz100.asm'
sed 's/^X//' <<'//go.sysin dd *' >msyz100.asm
; Kermit system dependent module for Heath/Zenith Z100
public term
include msdefs.h
BIOS_SEG SEGMENT AT 40H ; Define segment where BIOS really is
ORG 4*3
BIOS_PRINT LABEL FAR ; Printer output
ORG 6*3
BIOS_AUXOUT LABEL FAR ; AUX output routine
ORG 26*3
BIOS_AUXFUNC LABEL FAR ; AUX: function
ORG 27*3
BIOS_CONFUNC LABEL FAR ; CON: function
BIOS_SEG ENDS
; Function codes for BIOS_xxxFUNC
CHR_WRITE EQU 0 ; Write character
CHR_READ EQU 1 ; Read character
CHR_STATUS EQU 2 ; Get status
CHR_SFGS EQU 0 ; Get status subfunction
CHR_SFGC EQU 1 ; Get config subfunction
CHR_CONTROL EQU 3 ; Control function
CHR_CFSU EQU 0 ; Set new configuration parameters
CHR_CFCI EQU 1 ; Clear input buffer
; Scan code definitions used for translating back to Heath ESC sequences
entscan equ 08dh ; enter key scan code
f0scan equ 096h ; F0 key
f1scan equ 097h ; F1 key
f2scan equ 098h ; F2 key
f3scan equ 099h ; F3 key
f4scan equ 09ah ; F4 key
f5scan equ 09bh ; F5 key
f6scan equ 09ch ; F6 key
f7scan equ 09dh ; F7 key
f8scan equ 09eh ; F8 key
f9scan equ 09fh ; F9 key
f10scn equ 0a0h ; F10 key
f11scn equ 0a1h ; F11 key
f12scn equ 0a2h ; F12 key
homscan equ 0a9h ; Home key
upscan equ 0a5h ; Up arrow
dnscan equ 0a6h ; Down arrow
rtscan equ 0a7h ; Right arrow
lfscan equ 0a8h ; Left arrow
kpminus equ 0adh ; keypad minus
kpdot equ 0aeh ; keypad period
kp0 equ 0b0h ; keypad 0
kp1 equ 0b1h ; keypad 1
kp2 equ 0b2h ; keypad 2
kp3 equ 0b3h ; keypad 3
kp4 equ 0b4h ; keypad 4
kp5 equ 0b5h ; keypad 5
kp6 equ 0b6h ; keypad 6
kp7 equ 0b7h ; keypad 7
kp8 equ 0b8h ; keypad 8
kp9 equ 0b9h ; keypad 9
sentscn equ 0cdh ; shifted enter key
sf0scan equ 0d6h ; shifted F0 key
sf1scan equ 0d7h ; shifted F1 key
sf2scan equ 0d8h ; shifted F2 key
sf3scan equ 0d9h ; shifted F3 key
sf4scan equ 0dah ; shifted F4 key
sf5scan equ 0dbh ; shifted F5 key
sf6scan equ 0dch ; shifted F6 key
sf7scan equ 0ddh ; shifted F7 key
sf8scan equ 0deh ; shifted F8 key
sf9scan equ 0dfh ; shifted F9 key
sf10scn equ 0e0h ; shifted F10 key
sf11scn equ 0e1h ; shifted F11 key
sf12scn equ 0e2h ; shifted F12 key
shomscn equ 0e9h ; shifted Home key
supscan equ 0e5h ; shifted Up arrow
sdnscan equ 0e6h ; shifted Down arrow
srtscan equ 0e7h ; shifted Right arrow
slfscan equ 0e8h ; shifted Left arrow
skpmins equ 0edh ; shifted keypad minus
skpdot equ 0eeh ; shifted keypad period
skp0 equ 0f0h ; shifted keypad 0
skp1 equ 0f1h ; shifted keypad 1
skp2 equ 0f2h ; shifted keypad 2
skp3 equ 0f3h ; shifted keypad 3
skp4 equ 0f4h ; shifted keypad 4
skp5 equ 0f5h ; shifted keypad 5
skp6 equ 0f6h ; shifted keypad 6
skp7 equ 0f7h ; shifted keypad 7
skp8 equ 0f8h ; shifted keypad 8
skp9 equ 0f9h ; shifted keypad 9
; Miscellaneous scan codes used for functions
prscan equ f12scn ; print-screen scan code (F12)...
brkscan equ 0aah ; Break key
modfrm struc ; format of mode line
db 'Esc chr: '
m_echr db 2 dup (?)
db ', Speed: '
m_baud db 4 dup (?)
db ', Parity: '
m_par db 4 dup (?)
db ', Echo: '
m_echo db 3 dup (?)
db ', Prn: '
m_prs db 3 dup (?)
db ', Type '
m_hlp db 2 dup (?)
db '? for Help$'
modfrm ends
datas segment public 'datas'
waste db 100h dup(?) ; assembler problem???
flags1 db 0 ; internal flags
prtscr equ 80h ; print screen pressed flag
; Key translations - F12 is printscreen
ckeys db brkscan,prscan,upscan,dnscan,lfscan,rtscan,homscan
db entscan,f0scan,f1scan,f2scan,f3scan,f4scan,f5scan,f6scan
db f7scan,f8scan,f9scan,f10scn,f11scn,kpminus
db kpdot,kp0,kp1,kp2,kp3,kp4,kp5,kp6,kp7,kp8,kp9
db supscan,sdnscan,slfscan,srtscan,shomscn
db sentscn,sf0scan,sf1scan,sf2scan,sf3scan,sf4scan,sf5scan,sf6scan
db sf7scan,sf8scan,sf9scan,sf10scn,sf11scn,skpmins
db skpdot,skp0,skp1,skp2,skp3,skp4,skp5,skp6,skp7,skp8,skp9
lckeys equ $-ckeys
;ckacts must parallel ckeys above...
ckacts dw trnbrk,trnprs,trnupw,trndnw,trnlfw,trnrgw,trnhom,trnkpn
dw trnf0,trnf1,trnf2,trnf3,trnf4,trnf5,trnf6,trnf7,trnf8,trnf9
dw trnf10,trnf11,trnkpn,trnkpn,trnkpn,trnkpn,trnkpn
dw trnkpn,trnkpn,trnkpn,trnkpn,trnkpn,trnkpn,trnkpn
dw trnupw,trndnw,trnlfw,trnrgw,trnhom,trnkps
dw trnsf0,trnsf1,trnsf2,trnsf3,trnsf4,trnsf5,trnsf6,trnsf7
dw trnsf8,trnsf9,trnsf10,trnsf11,trnkps,trnkps
dw trnkps,trnskp1,trnskp2,trnskp3,trnskp4,trnskp5,trnskp6
dw trnskp7,trnskp8,trnskp9
enascan db ESC,'y?$' ; Enable scan codes
disscan db ESC,'x?$' ; Disable scan codes
uptrn db esc,'A'
dntrn db esc,'B'
rgtrn db esc,'C'
lftrn db esc,'D'
enttrn db cr ; enter key translation
homtrn db ESC,'H' ; home key translation
dottrn db '.' ; keypad . translation
mintrn db '-' ; keypad - translation
kp0trn db '0' ; keypad 0 translation
kp1trn db '1' ; keypad 1 translation
kp2trn db '2' ; keypad 2 translation
kp3trn db '3' ; keypad 3 translation
kp4trn db '4' ; keypad 4 translation
kp5trn db '5' ; keypad 5 translation
kp6trn db '6' ; keypad 6 translation
kp7trn db '7' ; keypad 7 translation
kp8trn db '8' ; keypad 8 translation
kp9trn db '9' ; keypad 9 translation
senttrn db cr ; shifted enter key translation
shomtrn db ESC,'H' ; home key translation
sdottrn db '.' ; shifted keypad . translation
smintrn db '-' ; shifted keypad - translation
skp0trn db '0' ; shifted keypad 0 translation
skp1trn db ESC,'L' ; shifted keypad 1 translation
skp2trn db ESC,'B' ; shifted keypad 2 translation
skp3trn db ESC,'M' ; shifted keypad 3 translation
skp4trn db ESC,'D' ; shifted keypad 4 translation
skp5trn db ESC,'H' ; shifted keypad 5 translation
skp6trn db ESC,'C' ; shifted keypad 6 translation
skp7trn db ESC,'@' ; shifted keypad 7 translation
skp8trn db ESC,'A' ; shifted keypad 8 translation
skp9trn db ESC,'N' ; shifted keypad 9 translation
f0trn db ESC,'J' ; F0 translation
f1trn db ESC,'S' ; F1 translation
f2trn db ESC,'T' ; F2 translation
f3trn db ESC,'U' ; F3 translation
f4trn db ESC,'V' ; F4 translation
f5trn db ESC,'W' ; F5 translation
f6trn db ESC,'P' ; F6 translation
f7trn db ESC,'Q' ; F7 translation
f8trn db ESC,'R' ; F8 translation
f9trn db ESC,'0I' ; F9 translation
f10trn db ESC,'0J' ; F10 translation
f11trn db ESC,'0K' ; F11 translation
f12trn db ESC,'0L' ; F12 translation
sf0trn db ESC,'E' ; shifted F0 translation
sf1trn db ESC,'1A' ; shifted F1 translation
sf2trn db ESC,'1B' ; shifted F2 translation
sf3trn db ESC,'1C' ; shifted F3 translation
sf4trn db ESC,'1D' ; shifted F4 translation
sf5trn db ESC,'1E' ; shifted F5 translation
sf6trn db ESC,'1F' ; shifted F6 translation
sf7trn db ESC,'1G' ; shifted F7 translation
sf8trn db ESC,'1H' ; shifted F8 translation
sf9trn db ESC,'1I' ; shifted F9 translation
sf10trn db ESC,'1J' ; shifted F10 translation
sf11trn db ESC,'1K' ; shifted F11 translation
sf12trn db ESC,'1L' ; shifted F12 translation
ourarg termarg <>
modbuf modfrm <> ; mode line buffer
; some static data for mode line
unkbaud db 'Unk ' ; must be 4 chars...
baudn db '45.5'
db ' 50'
db ' 75'
db ' 110'
db ' 135'
db ' 150'
db ' 300'
db ' 600'
db '1200'
db '1800'
db '2000'
db '2400'
db '4800'
db '9600'
db ' 19K'
db ' 38K'
baudnsiz equ 16 ; # of baud rates known (tbl size / 4)
parnams db 'Even'
db 'Mark'
db 'None'
db 'Odd ' ; must be 4 chars
db 'Spc '
offmsg db 'Off'
onmsg db 'On '
lclmsg db 'Lcl'
remmsg db 'Rem'
datas ends
code segment public
extrn prtchr:near,outchr:near,putmod:near,clrmod:near,sendbr:near
assume cs:code,ds:datas
; This is from the dumb terminal emulator routine in MSXGEN.ASM.
; Had to use bios calls because DOS calls were losing chars.
term proc near
mov si,ax ; this is source
mov di,offset ourarg ; place to store arguments
mov ax,ds
push es ; save caller's extra segment address
mov es,ax ; address destination segment
mov cx,size termarg
rep movsb ; copy into our arg blk
and flags1,not (prtscr) ; print screen mode disabled
test ourarg.flgs,emheath ; Are we to use Heath sequences?
jnz chkmod ; no, do something else
mov ah,prstr
mov dx,offset enascan ; enable scan codes
int dos
chkmod: call clrmod ; clear mode line
test ourarg.flgs,modoff ; is mode line disabled?
jnz term1 ; yes, skip it
call modlin ; turn on mode line
term1: call portchr ; char at port?
jnc term3 ; no, keep going
call outtty ; print on terminal
term3: mov ah,chr_status
mov al,chr_sfgs ; get number of characters
call bios_confunc ; check console
cmp bl,0
jz term1 ; no character, go on
mov ah,chr_read
call bios_confunc ; read it
cmp al,ourarg.escc ; escape char?
je term4 ; yes, exit
push ax ; save char
mov ah,al
call trnout ; translate if nec., output to port
pop ax
jmp term1 ; else echo and keep going
term4: call clrmod
mov ah,prstr
mov dx,offset disscan ; disable scan code generation
int dos
pop es
ret
term endp
; returns with carry on if a character is available
portchr proc near
call prtchr ; character at port?
jmp short portc1 ; yes, go handle
nop ; skip return is stupid
clc ; no carry -> no character
ret
portc1: and al,7fh ; we don't worry about parity here
stc ; have a character
ret
portchr endp
; put the character in al to the screen
outtty proc near
mov ah,chr_write
call bios_confunc
test ourarg.flgs,capt ; capturing output?
jz outtt1 ; no, forget it
call ourarg.captr ; else call the routine
outtt1: test flags1,prtscr ; print screen?
jz outtt2 ; no, try something else
call bios_print
outtt2: ret
outtty endp
; send the character in al out to the serial port
; handle echoing also...
outprt proc near
test ourarg.flgs,lclecho ; echoing?
jz outpr1 ; no, forget it
push ax ; save char
call outtty ; print it
pop ax ; restore
outpr1: mov ah,al ; this is where outchr expects it
call outchr ; output to the port
nop
nop
nop ; skip returns...
ret
outprt endp
modlin proc near ; turn on mode line
mov al,ourarg.escc
mov modbuf.m_echr,' ' ; first char is initial space
mov modbuf.m_hlp,' ' ; goes here too.
cmp al,32 ; printable?
jnb modl1 ; yes, keep going
add al,40h ; made printable
mov modbuf.m_echr,'^' ; note control char
mov modbuf.m_hlp,'^'
modl1: mov modbuf.m_echr+1,al ; fill in character
mov modbuf.m_hlp+1,al
mov al,ourarg.baudb ; get baud bits
mov si,offset unkbaud ; assume unknown baud
cmp al,baudnsiz ; too big?
jnb modl2 ; yes, use default
mov cl,2 ; each is 4 bytes long
shl al,cl
mov ah,0
add ax,offset baudn
mov si,ax
modl2: mov cx,size m_baud ; length of baud space
mov di,offset modbuf.m_baud
rep movsb ; copy in baud rate
mov al,ourarg.parity ; get parity code
mov cl,2 ; each is 4 bytes long...
shl al,cl
mov ah,0
add ax,offset parnams ; names of parity settings
mov si,ax
mov cx,4 ; each is 4 long
mov di,offset modbuf.m_par
rep movsb
mov si,offset remmsg ; assume remote echoing
test ourarg.flgs,lclecho ; echoing?
jz modl4 ; no, keep going
mov si,offset lclmsg
modl4: mov cx,3 ; size of on/off
mov di,offset modbuf.m_echo
rep movsb
; mov al,'1'
; cmp portno,1 ; port 1?
; je modl5 ; yes, keep going
; mov al,'2'
;modl5: mov modbuf.m_prt,al ; fill in port number
; mov cx,size modfrm ; this is size of mode line
; mov si,offset modbuf ; mode line image
mov si,offset offmsg ; assume printer off
test flags1,prtscr ; print screen enabled?
jz modl5 ; no, keep going
mov si,offset onmsg
modl5: mov cx,3
mov di,offset modbuf.m_prs
rep movsb
mov dx,offset modbuf
call putmod
ret ; and return
modlin endp
; translate the scan code in ah according to the translate table
; given in ktrntab/krpltab, output to port. If no translation,
; use ascii char in al. (should probably include shift state
; somewhere). Shift state is in bl.
trnout proc near
test ourarg.flgs,havtt ; translate table given?
jz trnou3 ; no, just output character
cmp ourarg.klen,0 ; did they say we have one
je trnou3 ; but we really don't?
push ax ; save original value
xor ah,ah ; Zero top half
mov di,ourarg.ktab
mov cx,ourarg.klen
repne scasw ; look for our key
pop ax ; recover character
jne trnou3 ; not found, forget it
sub di,ourarg.ktab
sub di,2 ; (minus 2 for pre-increment)
mov bx,ourarg.krpl
mov si,[bx][di] ; and addr of replacement
mov cl,[si] ; get first byte (length)
xor ch,ch ; clear high-order byte
inc si ; point to translation string
trnou2: lodsb ; get a byte
push si
push cx ; save important registers
call outprt ; send to port
pop cx
pop si
loop trnou2 ; send all chars
ret ; and return
trnou3: xor ah,ah ; get scan code
mov cx,lckeys ; length of table
mov di,offset ckeys ; table address
repne scasb
; mov al,0 ; ascii code was 0...
jne trnou4 ; not found, keep going
sub di,offset ckeys+1 ; get table offset
shl di,1 ; shift for word offset
jmp ckacts[di] ; jump to appropriate routine
trnou4: call outprt ; just output single char
ret ; and return
;trnmod: test flags,modoff ; mode line already off?
; jnz trnm1 ; yes, go turn on
; call clrmod ; no, clear mode line here
; or flags,modoff ; turn on flag
; ret ; and return
;trnm1: call modlin ; turn on mode line
; and flags,not modoff ; clear flag
; ret ; and return
trnbrk:
call sendbr
ret
trnprs: xor flags1,prtscr ; flip the flag
and ourarg.flgs,not modoff ; turn on mode line
call modlin ; write into mode line
ret ; and return
trn1ch: mov cx,1 ; length is always 1
jmp trnou2
; common entry for arrow keys
trn2ch: mov cx,2 ; length is always 2
jmp trnou2 ; go send definition
trn3ch: mov cx,3 ; length is always 3
jmp trnou2
trnupw: mov si,offset uptrn
jmp trn2ch
trndnw: mov si,offset dntrn
jmp trn2ch
trnlfw: mov si,offset lftrn
jmp trn2ch
trnrgw: mov si,offset rgtrn
jmp trn2ch
trnhom: mov si,offset homtrn
jmp trn2ch
trnent: mov si,offset enttrn
jmp trn1ch
trnf0: mov si,offset f0trn
jmp trn2ch
trnf1: mov si,offset f1trn
jmp trn2ch
trnf2: mov si,offset f2trn
jmp trn2ch
trnf3: mov si,offset f3trn
jmp trn2ch
trnf4: mov si,offset f4trn
jmp trn2ch
trnf5: mov si,offset f5trn
jmp trn2ch
trnf6: mov si,offset f6trn
jmp trn2ch
trnf7: mov si,offset f7trn
jmp trn2ch
trnf8: mov si,offset f8trn
jmp trn2ch
trnf9: mov si,offset f9trn
jmp trn3ch
trnf10: mov si,offset f10trn
jmp trn3ch
trnf11: mov si,offset f11trn
jmp trn3ch
trnkpn: and al,07fh ; strip high bits
jmp trnou4 ; now output it
trnkps: and al,03fh ; strip high bits (special case)
jmp trnou4
trnsf0: mov si,offset sf0trn
jmp trn2ch
trnsf1: mov si,offset sf1trn
jmp trn3ch
trnsf2: mov si,offset sf2trn
jmp trn3ch
trnsf3: mov si,offset sf3trn
jmp trn3ch
trnsf4: mov si,offset sf4trn
jmp trn3ch
trnsf5: mov si,offset sf5trn
jmp trn3ch
trnsf6: mov si,offset sf6trn
jmp trn3ch
trnsf7: mov si,offset sf7trn
jmp trn3ch
trnsf8: mov si,offset sf8trn
jmp trn3ch
trnsf9: mov si,offset sf9trn
jmp trn3ch
trnsf10: mov si,offset sf10trn
jmp trn3ch
trnsf11: mov si,offset sf11trn
jmp trn3ch
trnskp1: mov si,offset skp1trn
jmp trn2ch
trnskp2: mov si,offset skp2trn
jmp trn2ch
trnskp3: mov si,offset skp3trn
jmp trn2ch
trnskp4: mov si,offset skp4trn
jmp trn2ch
trnskp5: mov si,offset skp5trn
jmp trn2ch
trnskp6: mov si,offset skp6trn
jmp trn2ch
trnskp7: mov si,offset skp7trn
jmp trn2ch
trnskp8: mov si,offset skp8trn
jmp trn2ch
trnskp9: mov si,offset skp9trn
jmp trn2ch
trnout endp
code ends
end
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 640 msyz100.asm
/bin/echo -n ' '; /bin/ls -ld msyz100.asm
fi
/bin/echo 'Extracting msz100.hlp'
sed 's/^X//' <<'//go.sysin dd *' >msz100.hlp
KERMIT VERSION 2.26 FOR Z-DOS
September 20, 1984
This guide is meant to be a supplement to the MSKERMIT.HLP file. It
describes the differences between the Z-100 version of Kermit and
the IBM-PC version. This version has not been tested with Z-DOS
version 2.0. LOCAL command execution may or may not work.
* Program Operation
The Z-100 version of Kermit uses a slightly different concept for
Heath emulation. The Z-100 normally uses the same escape sequences
as the Heathkit H-19 terminal, although a slightly different key
arrangement is used. With Heath emulation mode turned on, the normal
Z-100/H19 escape sequences will be sent by the function keys and keypad.
However, key redefinition will not be available. Printer control is
also not available in Heath emulation mode. When Heath emulation
is turned off (the default), the function keys and keypad emulate the
Heath sequence as best as possible (no checks are made for alternate
or shifted keypad modes), but key redefinition is allowed. If a problem
is encountered running a program that uses the keypad keys or function
keys, swicth to Heath emulation and see if that helps. Heath
emulation only affects what characters are sent for keys typed at the
keyboard. It does not change the affect of incoming characters or
escape sequences.
The Z-100 version of Kermit-MS does not support multiple communication
ports. The modem is assumed to be connected to the AUX port. This
port must be configured as no parity, no handshake, 1 stop bit, 8 data
bits, no pad.
* Terminal Emulation
The Z-DOS version of Kermit-MS uses the following capabilities:
Escape Char: ^]
Modeline
Printer control
Key redefinition (with Heath emulation off)
Screen scroll is not currently supported.
X. Printer Control
The contents of a screen may be printed at any time if a printscreen
driver has been installed prior to running Kermit. This is usually
done by running the PSC command which comes with your ZDOS 1.25
disks. After this, the screen contents may be printed using
Shift-F12.
If you wish to log a terminal session on the printer and you are not
using Heath emulation mode, the F12 function key will start or stop
the spooling of incoming characters to the printer. This may also
be simulated by the Kermit-MS LOG PRN and CLOSE commands.
X. Key Redefinition
Key redefinitions are accomplished in the same way as with the IBM-PC
version. However, key redefintion may only be used when Heath
emulation is turned off.
//go.sysin dd *
made=TRUE
if [ $made = TRUE ]; then
/bin/chmod 640 msz100.hlp
/bin/echo -n ' '; /bin/ls -ld msz100.hlp
fi
More information about the Comp.sources.unix
mailing list