home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
extra
/
nyenhuis2.arc
/
MSXGRI.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-07-01
|
34KB
|
1,268 lines
name msxgri
; File MSXGRI.ASM
; Grid Compass II dependent file for MS-DOS Kermit
; Use with msugri.asm keyboard translator file.
;
; Last edit: 12 June 1988
; 1 July 1988 Version 2.31
; 12 June 1988 Add error recovery if serial port fails to initialize, reduce
; serial port buffer to 1000 bytes. [jrd]
; 11 Jan 1988 Add 2.30 features. [jrd]
; 1 Jan 1988 version 2.30
;
; Jim Noble
; Planning Research Corporation
; 1500 Planning Research Drive
; Mail Stop 5S3
; McLean, VA 22102
; May, 1985
; Add global entry point vtstat for use by Status in mssset.
; Added register save/restore in procedure getbaud.
; Joe R. Doupnik 12 March 1986
; Add global procedures ihosts and ihostr to handle host initialization
; when packets are to be sent or received by us,resp. 24 March 1986
; Add global procedure dtrlow (without worker serhng) to force DTR & RTS low
; in support of Kermit command Hangup. Says Not Yet Implemented. [jrd]
; Add global procedure Dumpscr, called by Ter in file msster, to dump screen
; to a file. Just does a beep for now. 13 April 1986 [jrd]
; In proc Outchr add override of xon from chkxon sending routine.
; This makes a hand typed Xoff supress the xon flow control character sent
; automatically as the receiver buffer empties. 20 April 1986 [jrd]
public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel, ctlu
public cmblnk, locate, prtchr, dobaud, clearl, lclini, getmodem
public dodisk, getbaud, beep, setkhlp, setktab, pcwait, trnprs
public machnam, xofsnt, count, term, poscur, serhng
public clrmod, putmod, puthlp, sendbr, sendbl, showkey, shomodem
public ihosts, ihostr, dtrlow, dumpscr, comptab, termtb ; [jrd]
public chrout, cstatus, cquit, cquery ; kbd action verbs
public snull, kdos, klogof, klogon
include mssdef.h
false equ 0
true equ 1
print_out equ 05h ; dos function to print to printer
prtscr equ 80h ; print screen pressed
gbuflen equ 1000 ; max bytes grid internal buffer holds
mntrgh equ gbuflen/2 ; High point = 1/2 of buffer full.
mntrgl equ bufsiz/4 ; Low point = 1/4 buffer full. [jrd]
gserial equ 81h ; grid serial port interrupt
gmodem equ 82h ; grid modem port interrupt
ginit equ 0 ; function 0 - initialize port
gread equ 1 ; function 1 - read data
gwrite equ 2 ; function 2 - write data
gwcmd equ 4 ; function 4 - write command
grstat equ 5 ; function 5 - read status
gflush equ 6 ; function 6 - buffer flush
ggbaud equ 7 ; function 7 - get baud
gsbaud equ 8 ; function 8 - set baud
gspar equ 9 ; function 9 - set parity
gsdata equ 10 ; function 10 - set data bits
gssbit equ 11 ; function 11 - set stop bits
gbufass equ 12 ; function 12 - buffer assign
gcharto equ 13 ; function 13 - set character timeout
gbrk equ 14 ; function 14 - break control
gcts equ 19 ; function 19 - clear to send timeout
gbrkon equ gbrk*100H+00H ; function 14 - set break on
gbrkoff equ gbrk*100H+0ffH ; function 14 - set break off
scnstrt equ 400h ; starting address of screen area (page 0)
scnwrds equ 4800 ; number of words in screen memory area
datas segment public 'datas'
extrn drives:byte, flags:byte, trans:byte
extrn portval:word, port1:byte, port2:byte, dmpname:byte
extrn kbdflg:byte, rxtable:byte
machnam db 'GRID COMPASS II version A'
curini db 0 ; [gaw@prc]
cursav db ESCAPE,'[s','$' ; [gaw@prc]
curres db ESCAPE,'[u','$' ; [gaw@prc]
curon db ESCAPE,'[3;3z','$' ; [gaw@prc]
curoff db ESCAPE,'[3;4z','$' ; [gaw@prc]
scrsav dw scnwrds DUP(?)
erms20 db cr,lf,'?Warning: System has no disk drives$'
erms40 db cr,lf,'?Warning: Unrecognized baud rate$'
badbd db cr,lf,'Unimplemented baud rate$'
crlf db cr,lf,'$'
comphlp db cr,lf,'1 (SERIAL) 2 (MODEM)$' ; [19b] [gaw@prc]
hngmsg db cr,lf,' The phone should have hungup.',cr,lf,'$'
hnghlp db cr,lf,' The modem control lines DTR and RTS for the current'
db ' port are forced low (off)'
db cr,lf,' to hangup the phone. Normally, Kermit leaves them'
db ' high (on) when it exits.'
db cr,lf,'$'
rdbuf db 80 dup (?) ; temp buf
noimp db cr,lf,'?Not implemented.$'
delstr db BS,' ',BS,'$' ; Delete string
clrlin db cr,ESCAPE,'[0K','$'
portin db 0 ; has clock int vector been initialized?
xofsnt db 0 ; Say if we sent an XOFF.
xofrcv db 0 ; Say if we received an XOFF.
insrvc db 0 ; Say if in service on XON/XOFF interrupt
parmsk db ? ; parity mask, 0ffh for no parity, 07fh with.
flowoff db ? ; flow-off char, Xoff or null (if no flow)
flowon db ? ; flow-on char, Xon or null
captrtn dw ? ; routine to call for captured output
invseq db ESCAPE,'[7m$' ; Reverse video.
nrmseq db ESCAPE,'[0m$' ; Normal mode.
ivlseq db 79 dup (' '),cr,'$' ; Make a line inverse video
tmp db ?,'$'
temp dw 0
temp1 dw ? ; Temporary storage.
temp2 dw ? ; Temporary storage.
fncerr db cr,lf,'Error on function '
fnctype db 'X with a status return of '
fncstat db 'Y$'
argadr dw ? ; address of arg blk
; key redefinitions
setktab db 0
setkhlp db 0
ontab db 2 ; Two entries.
mkeyw 'Off',0
mkeyw 'On',1
; Entries for choosing communications port.
comptab db 4 ; number of entries
mkeyw '1',1 ; com1
mkeyw '2',2 ; com2
mkeyw 'COM1',1
mkeyw 'COM2',2
termtb db 2
mkeyw 'none',ttgenrc
mkeyw 'VT52',ttvt52
; this table is indexed by the baud rate definitions given in
; pcdefs. Unsupported baud rates should contain -1.
; (*) - only two supported on modem
bddat label word
dw -1 ; 45.5 baud -- Not supported.
dw 0 ; 50 baud
dw 1 ; 75 baud
dw 2 ; 110 baud
dw 3 ; 134.5 baud
dw 4 ; 150 baud
dw 5 ; 300 baud - (*)
dw 6 ; 600 baud
dw 7 ; 1200 baud - (*)
dw 8 ; 1800 baud
dw 9 ; 2000 baud
dw 10 ; 2400 baud
dw 12 ; 4800 baud
dw 14 ; 9600 baud
dw 15 ; 19200 baud
dw -1 ; 38400 baud -- Not supported.
; variables for serial interrupt handler
gbuffer db gbuflen DUP(?) ; large internal buffer for grid [gaw@prc]
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
clreol db ESCAPE,'[0K$'
blank db ESCAPE,'[2J$'
movcur db ESCAPE,'['
colno db 20 dup (?)
ten db 10
ourarg termarg <>
datas ends
code segment public 'code'
extrn comnd:near, dopar:near, prserr:near, defkey:near
extrn sleep:near, msuinit:near, keybd:near
assume cs:code,ds:datas
; local initialization
lclini proc near
mov portin,0 ; serial port not yet initialized
mov flags.vtflg,0 ; turn off terminal emulation [gaw@prc]
call msuinit ; init keyboard translator
ret
lclini endp
; See how many disk drives we have.
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.
CLRBUF PROC NEAR
cli
mov ax,offset source
mov bufin,ax
mov bufout,ax
mov count,0
sti
clrb1: call prtchr ; get a character
jmp clrb1 ; until there aren't any more
nop
ret
CLRBUF ENDP
; Common routine to clear to end-of-line
CLEARL PROC NEAR
mov dx,offset clreol
mov ah,prstr
int dos
ret
CLEARL ENDP
SHOMODEM PROC NEAR ; display CD, CTS, DSR. Not implemented here
mov ah,prstr
mov dx,offset noimp
int dos
jmp rskp
SHOMODEM ENDP
getmodem proc near
mov al,0 ; modem status, none
ret
getmodem endp
; Do a grid function call to the correct com port and return
GRDFNC PROC NEAR
push es ; save es reg
push ds ; then mov ds to es
pop es
push ax ; save function call and value in al
add ah,"0" ; make function code printable
mov fnctype,ah ; and save in error message
pop ax ; restore ax
cmp flags.comflg,1 ; serial port or modem? [gaw@prc]
jne grdfnc1 ; if modem, do other int [gaw@prc]
int gserial ; else do serial port function call [gaw@prc]
jmp grdfnc2 ; skip other int [gaw@prc]
grdfnc1:
int gmodem ; do modem port function call [gaw@prc]
grdfnc2:
jnc grdfnc3 ; skip error msg if carry not set
add al,"0" ; make error code printable
mov fncstat,al ; and put in error message
mov ah,prstr
push dx
mov dx,offset fncerr ; Give an error message
int dos
pop dx
grdfnc3:
pop es ; restore es
ret
GRDFNC ENDP
; Set the baud rate for the current port, based on the value
; in the portinfo structure. Returns normally.
DOBAUD PROC NEAR
push ax ; save regs
push bx
mov bx,portval
mov temp1,ax ; Don't overwrite previous rate
mov ax,[bx].baud ; Check if new rate is valid
shl ax,1 ; index words
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
dobd01:
mov ax,temp1 ; Get back original value
mov bx,portval
mov [bx].baud,ax ; Leave baud rate as is
mov ah,prstr
mov dx,offset badbd ; Give an error message
int dos
pop bx
pop ax
ret
dobd0:
mov temp1,ax ; Remember value to output
cmp flags.comflg,1 ; is it com1?
je dobd1 ; yep, skip test for 300/1200
cmp ax,7 ; is it 1200 on com2?
je dobd1 ; yep, go do it
cmp ax,5 ; is it 300 on com2?
je dobd1 ; yep, go do it
jmp short dobd01 ; go give unimplemented msg
dobd1:
mov ah,gsbaud ; set up to set the port baudrate
call grdfnc ; do a grid function call to a com port
pop bx
pop ax
ret
DOBAUD ENDP
; Send a break out the current serial port. Returns normally.
sendbr proc near
push cx
push ax
xor cx,cx ; Clear loop counter
mov ax,gbrkon ; setup to do break on [gaw@prc]
call grdfnc ; do break on
pause: loop pause ; Wait a while
mov ax,gbrkoff ; setup to do break off [gaw@prc]
call grdfnc ; do break off
pop ax
pop cx
clc
ret ; And return
sendbr endp
SENDBL PROC NEAR ; send a long break
call sendbr ; do several of these
call sendbr
call sendbr
call sendbr
ret
SENDBL ENDP
; Send char in al out the serial port. Checks flow control.
; Return rskp if success, return rskp even if failure.
OUTCHR PROC NEAR
push bx
push cx
mov bx,portval
cmp [bx].floflg,0 ; Are we doing flow control
pop bx
je outch2 ; No, just continue
xor cx,cx ; clear counter
cmp ah,flowoff ; sending xoff?
jne outch1 ; ne = no
mov xofsnt,false ; supress xon from chkxon buffer routine
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:
mov byte ptr temp,ah ; put character in buffer
push di ; Save register
mov cx,1 ; set up to write one char to a grid port
mov di,offset temp
mov ah,gwrite
call grdfnc ; go write a character
pop di ; restore saved registers
pop cx
jmp rskp
OUTCHR ENDP
; This routine blanks the screen.
CMBLNK PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset blank
int dos
pop dx
pop ax
ret
CMBLNK ENDP
LOCATE PROC NEAR
mov dx,0 ; Go to top left corner of screen.
jmp poscur ; callret...
LOCATE 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
push ax ; save some regs
push bx
push cx
push dx
mov ah,ggbaud ; set up to get port baud rate
call grdfnc ; and go get it
mov al,ah ; mov baudrate into al
mov ah,0 ; and zero upper part of ax
mov bx,offset bddat ; Find rate's offset into table
mov cl,0 ; Keep track of index
getb0: cmp ax,[bx]
je getb1
inc cl
cmp cl,baudsiz ; At the end of the list
jge getb2
add bx,2
jmp getb0
getb1: mov ch,0
mov bx,portval
mov [bx].baud,cx ; Set baud rate
jmp short getb3
getb2: mov ah,prstr
mov dx,offset erms40
int dos
getb3: pop dx ; restore regs
pop cx
pop bx
pop ax
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
push si
cmp count,0 ; any characters?
jne prtch2 ; ne = yes, get from buffer
prtch1:
push di
push bx
push cx
mov cx,bufsiz ; set up to read from grid port buffer
mov di,offset source
mov ah,gread
call grdfnc
pop cx ; restore saved registers
pop bx
pop di
mov count,ax ; reset count
or ax,ax
jz prtch4 ; still no chars
mov bufout,offset source ; this is output ptr
prtch2:
dec count
mov dx,count ; return count in dx
mov si,bufout
cld
lodsb ; get character
mov bufout,si ; update ptr
pop si
ret
prtch4:
pop si
jmp rskp ; no chars
PRTCHR ENDP
; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
; else repeat cycle. Requires that the port be initialized before hand.
; Ihosts is used by the local send-file routine just after initializing
; the serial port.
; 22 March 1986 [jrd]
IHOSTS PROC NEAR
push ax ; save the registers
push bx
push cx
push dx
mov bx,portval ; port indicator
mov ax,[bx].flowc ; put Go-ahead flow control char in ah
or ah,ah ; don't send null if flow = none
jz ihosts1 ; z = null
call outchr ; send it (release Host's output queue)
nop ; outchr can do skip return
nop
nop
ihosts1:call clrbuf ; clear out interrupt buffer
pop dx ; empty buffer. we are done here
pop cx
pop bx
pop ax
ret
IHOSTS ENDP
; IHOSTR - initialize the remote host for our reception of a file by
; sending the flow-on character (XON typically) to release any held
; data. Called by receive-file code just after initializing the serial
; port. 22 March 1986 [jrd]
IHOSTR PROC NEAR
push ax ; save regs
push bx
push cx
mov bx,portval ; port indicator
mov ax,[bx].flowc ; put Go-ahead flow control char in ah
or ah,ah ; don't send null if flow = none
jz ihostr1 ; z = null
call outchr ; send it (release Host's output queue)
nop ; outchr can do skip return
nop
nop
ihostr1:pop cx
pop bx
pop ax
ret
IHOSTR ENDP
DTRLOW PROC NEAR ; Global proc to Hangup the Phone by making
; DTR and RTS low.
mov ah,cmtxt ; allow text to be able to display help
mov bx,offset rdbuf ; dummy buffer
mov dx,offset hnghlp ; help message
call comnd ; get a confirm
jmp r
; not yet imp. call serhng ; drop DTR and RTS
mov ah,prstr ; give a nice message
; not yet imp. mov dx,offset hngmsg
mov dx,offset noimp ; for now
int dos
clc
jmp rskp
DTRLOW ENDP
; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
; to terminate the connection. 29 March 1986 [jrd]
; Calling this twice without intervening calls to serini should be harmless.
; Returns normally.
; SERHNG is Not Yet Implemented.
SERHNG PROC NEAR
ret
SERHNG ENDP
; Wait for the # of milliseconds in ax, for non-IBM compatibles.
; Based on 4.77 Mhz 8088 processor speeds.
; Thanks to Bernie Eiben for this one.
pcwait proc near
mov cx,240 ; inner loop counter for 1 millisecond
pcwai1: sub cx,1 ; inner loop takes 20 clock cycles
jnz pcwai1
dec ax ; outer loop counter
jnz pcwait ; wait another millisecond
ret
pcwait endp
; Position the cursor according to contents of DX.
POSCUR PROC NEAR
push ax ; save regs
push dx
push es
push di
mov ax,ds
mov es,ax ; address data segment!!!
cld
mov di,offset colno
mov al,dh ; row
inc al ; adjust offset from 1 instead of 0
mov ah,0 ; zero up half of reg containing number
call nout
mov al,';'
stosb
mov al,dl ; column
inc al ; adjust offset from 1 instead of 0
mov ah,0 ; zero up half of reg containing number
call nout
mov al,'H'
stosb
mov al,'$'
stosb
mov dx,offset movcur
mov ah,prstr
int dos ; print the sequence
pop di
pop es
pop dx
pop ax
ret
POSCUR ENDP
; put the number in ax into the buffer pointed to by di. Di is updated
nout proc near
push dx ; save registers
push bx
push ax
cld
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
pop ax ; restore all registers
pop bx
pop dx
ret
nout 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,26 * 100H ; line 26
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,26 * 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
pop si ; Put message address here
puth0: mov ah,prstr
mov dx,offset invseq ; Put into reverse video
int dos
mov ah,prstr
mov dx,offset ivlseq ; Make line inverse video
int dos
cld
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 crlf
mov ah,prstr
int dos
mov dx,offset nrmseq ; Normal video
int dos
clc
ret
puthlp endp
; Perform a delete.
DODEL PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset delstr ; Erase character
int dos
pop dx
pop ax
ret
DODEL ENDP
; Perform a Control-U.
CTLU PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset clrlin
int dos
pop dx
pop ax
ret
CTLU ENDP
COMS PROC NEAR
mov dx,offset comptab
mov bx,offset comphlp
mov ah,cmkey
call comnd
jmp r
nop
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
clc ; carry clear for success
ret
coms0: mov ax,offset port2
mov portval,ax
clc ; carry clear for success
ret
comx: pop bx
stc ; carry set for failure
ret
COMS ENDP
; Set heath emulation on/off.
VTS PROC NEAR
mov dx,offset termtb
mov bx,0
mov ah,cmkey
call comnd
jmp r
nop
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 VT52 emulation flag
ret
vt0: pop bx
ret
VTS ENDP
VTSTAT PROC NEAR ; For Status display [jrd]
ret ; no emulator status to display
VTSTAT ENDP
; Save the screen to a buffer and then append buffer to a disk file. [jrd]
; Default filename is Kermit.scn; actual file can be a device too. Filename
; is determined by mssset and is passed as pointer dmpname.
DUMPSCR PROC NEAR ; Dumps screen contents to a file. Just Beeps here
call beep ; [jrd]
clc
ret
DUMPSCR 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
ret ; and return
showkey endp
; Common initialization for using serial port.
SERINI PROC NEAR
push es
cmp portin,0 ; Did we initialize interrupt already?
je serin0 ; No, skip exit
jmp serin1 ; Yes, so just leave
serin0: cli ; Disable interrupts
cld ; Do increments in string operations
xor ax,ax ; get vector of clock tick int at 1CH
mov es,ax
mov bx,1Ch*4
mov ax,es:[bx]
mov cs:savclko,ax
add bx,2
mov ax,es:[bx]
mov cs:savclks,ax
;-> all because cli doesn't disable clock tick interrupt!
push es ; save pointer to segment part of vector
push bx
mov es,ax ; point to location with offset replaced
mov bx,offset serint
mov cl,es:[bx] ; save value in cl
mov al,0CFh ; load al with IRET instruction
mov es:[bx],al ; put at location with offset replace
pop bx
pop es
sub bx,2 ; now point to offset part of vector
mov ax,offset serint
mov es:[bx],ax ; and load with offset of serint
add bx,2 ; now point to segment part of vector
mov ax,cs
mov es:[bx],ax ; and load with code segement address
mov ax,cs:savclks ; now restore byte at offset of serint
mov es,ax
mov bx,offset serint
mov es:[bx],cl
;<-
mov portin,1 ; Remember interrupt has been initialized
sti ; turn interrupts back on
call dobaud ; reset baud just incase modem hung up
xor ax,ax
mov ah,gspar ; parity = none
call grdfnc
mov al,1 ; stopbit = 1
mov ah,gssbit
call grdfnc
mov al,8 ; data bits = 8
mov ah,gsdata
call grdfnc
mov dx,1 ; timeout on char read wait = 1ms
mov ah,gcharto
call grdfnc
cmp flags.comflg,1 ; Using Com 1?
jne skipcts ; Nope.
mov dx,0 ; timeout on cts = 0
mov ah,gcts
call grdfnc
skipcts:mov ax,ds ; point to large buffer
mov es,ax
mov di,offset gbuffer
mov cx,gbuflen
mov ah,gbufass
call grdfnc
mov ah,gflush ; flush grid input buffer
call grdfnc
push bx
mov bx,portval ; get port
mov parmsk,0ffh ; parity mask, assume parity is None
cmp [bx].parflg,parnon ; is it None?
je serin2 ; e = yes
mov parmsk,07fh ; no, pass lower 7 bits as data
serin2: mov bx,[bx].flowc ; get flow control chars
mov flowoff,bl ; xoff or null
mov flowon,bh ; xon or null
pop bx
call clrbuf ; Clear input buffer
serin1: pop es
clc ; carry clear for success
ret
SERINI ENDP
SERRST PROC NEAR
cmp portin,0 ; Did we initialize interrupt already?
je serrst0 ; No, skip resetting clock vector
cli ; Disable interrupts
;-> all because cli doesn't disable clock tick interrupt!
push es ; restore vector of clock tick int at 1CH
mov ax,cs:savclks ; get pointer to location when segment replaced
mov es,ax
mov bx,offset serint
mov cl,es:[bx] ; save value from there in cl
mov al,0CFh ; load location with IRET
mov es:[bx],al
push es ; save segment pointer for later
push bx
xor ax,ax ; point to segment part of vector
mov es,ax
mov bx,(1Ch*4)+2
mov ax,cs:savclks ; replace with original value
mov es:[bx],ax
sub bx,2 ; now replace offset with original value
mov ax,cs:savclko
mov es:[bx],ax
pop bx ; now restore location holding temporary IRET
pop es
mov es:[bx],cl
pop es ; and clean up stack
;<-
mov portin,0 ; Remember interrupt has been reset.
sti ; turn interrupts back on
serrst0:
ret ; All done
SERRST ENDP
; Comm port interrupt service routine to prevent grid buffer overflow
; sends Xoff if necessary if activated
;
SERINT PROC NEAR
push ax
push bx
push cx
push dx
push ds
push es
push si
push di
push bp
pushf
cld
mov ax,seg datas
mov ds,ax ; address data segment
mov es,ax
mov bx,portval
cmp [bx].floflg,0 ; Doing flow control?
je retint ; No, just leave.
jmp retint ; <<===<< temporary stub until grid problem resolved
cmp insrvc,true ; are we already doing interrupt service?
je retint ; yes, then skip service until this one done
mov insrvc,true ; nope, set in service flag
sti ; flag set enable interrupts
mov ah,grstat ; get the buffer count
call grdfnc
cmp xofsnt,true ; Have we sent an XOFF?
je serint1 ; Yes.
cmp cx,mntrgh ; Past the high trigger point?
jbe intdone ; No, we're within our limit
mov ah,flowoff ; Get the XOFF
or ah,ah ; null (no flow control)?
jz intdone ; z = yes, do nothing
mov byte ptr temp,ah ; put character in buffer
mov cx,1 ; set up to write one char to a grid port
mov di,offset temp
mov ah,gwrite
call grdfnc ; go write a character
mov xofsnt,true ; Remember we sent it
jmp intdone
serint1:
cmp cx,mntrgl ; below the low trigger point?
ja intdone ; no, don't send XON
mov ah,flowon ; get the XON
or ah,ah ; null?
jz intdone ; z = yes, do nothing
mov byte ptr temp,ah ; put character in buffer
mov cx,1 ; set up to write one char to a grid port
mov di,offset temp
mov ah,gwrite
call grdfnc ; go write a character
mov xofsnt,false ; remember we sent it
intdone:
mov insrvc,false ; set in service flag to false
retint:
sti
popf
pop bp
pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:savclko
savclko dw ? ; save clock tick interrupt vector offset
savclks dw ? ; save clock tick interrupt vector segment
SERINT ENDP
; Generate a short beep.
BEEP PROC NEAR
mov dl,bell
mov ah,conout
int dos
ret
BEEP ENDP
; put the character in al to the screen, do capture and printing,
; does translation for Set Input command.
; Adapted from msyibm.asm [jrd]
outtty proc near
test flags.remflg,d8bit ; keep 8 bits for displays?
jnz outnp8 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
outnp8: cmp rxtable+256,0 ; is translation off?
je outnp7 ; e = yes, off
push bx ; Translate incoming char [jrd]
mov bx,offset rxtable ; address of translate table [jrd]
xlatb ; new char is in al
pop bx
outnp7:
push bx
mov bx,argadr ; args from msster directly
test [bx].flgs,capt ; capturing output? Can be shut off
pop bx ; if out dev becomes not ready
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 ourarg.flgs,prtscr ; should we be printing?
jz outnop ; no, keep going
push ax
mov ah,print_out ; write to system printer device
mov dl,al
int dos
pop ax
jnc outnop ; nc = successful print
push ax
call beep ; else make a noise and
call trnprs ; turn off printing
pop ax
outnop: cmp flags.vtflg,0 ; emulating a terminal?
jnz outnop1 ; nz = yup, go do something smart
test ourarg.flgs,trnctl ; debug? if so use dos tty mode
jz outnp4 ; z = no
mov ah,conout
cmp al,7fh ; Ascii Del char or greater?
jb outnp1 ; b = no
je outnp0 ; e = Del char
push ax ; save the char
mov dl,7eh ; output a tilde for 8th bit
int dos
pop ax ; restore char
and al,7fh ; strip high bit
outnp0: cmp al,7fh ; is char now a DEL?
jne outnp1 ; ne = no
and al,3fH ; strip next highest bit (Del --> '?')
jmp outnp2 ; send, preceded by caret
outnp1: cmp al,' ' ; control char?
jae outnp3 ; ae = no
add al,'A'-1 ; make visible
outnp2: push ax ; save char
mov dl,5eh ; caret
int dos ; display it
pop ax ; recover the non-printable char
outnp3: mov dl,al
int dos
ret
outnp4: cmp al,bell ; bell (Control G)? [jrd]
jne outnp5 ; ne = no
jmp beep ; use short beep, avoid char loss.
outnop1:
outnp5: mov ah,conout ; dostty screen mode
mov dl,al ; write without intervention.
int dos ; else let dos display char
ret ; and return
outtty 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
; Get a char from the serial port manager
; returns with carry on if a character is available
portchr proc near
call prtchr ; character at port?
jmp short portc1 ; yes, go handle
nop
portc0: clc ; no carry -> no character
ret ; and return
portc1: and al,parmsk ; apply 8/7 bit parity mask
or al,al ; null?
jz portc0 ; z = yes, ignore
cmp al,DEL ; ascii DEL code?
je portc0 ; e = yes, ignore
stc ; have a character
ret ; and return
portchr 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
mov flags,al ; mask for allowable and save
; and flags1,not (prtscr) ; these are allowable
; (others remain).
mov ax,[bx].captr
mov captrtn,ax ; buffer capture routine
mov parmsk,0ffh ; parity mask, assume parity = None
cmp [bx].parity,parnon ; is parity None?
je argin2 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
argin2: ret ; that's it
argini endp
term proc near
mov argadr,ax ; save argument ptr
push es
mov si,ax ; this is source
mov di,offset ourarg ; place to store arguments
push ds
pop es ; address destination segment
mov cx,size termarg
cld
rep movsb ; copy into our arg blk
pop es
call argini ; init options from arg address
cmp curini,0 ; have we been in here before[gaw@prc]
je term1 ; if not skip restoring cursor[gaw@prc]
call restscr ; restore screen
cmp flags.vtflg,0 ; are we in emulation mode[gaw@prc]
jne term1 ; to skip restoring cursor[gaw@prc]
mov ah,prstr ; send '<esc>[u' to ansi.sys[gaw@prc]
mov dx,offset curres ; [gaw@prc]
int dos ; [gaw@prc]
term1: call portchr ; read char from serial port
jnc short term3 ; nc = no char, go on
call outtty ; display and capture char [jrd]
term3: call keybd ; call keyboard xlator, send results
jnc term1 ; nc = stay in Connect mode
cmp flags.vtflg,0 ; are we in emulation mode[gaw@prc]
jne term5 ; if we are skip saving cursor[gaw@prc]
mov ah,prstr ; send '<esc>[s' to ansi.sys[gaw@prc]
mov dx,offset cursav ; [gaw@prc]
int dos ; [gaw@prc]
mov byte ptr curini,1 ; now we've saved the cursor[gaw@prc]
term5: ; [gaw@prc]
call savescr ; save screen [gaw@prc]
mov al,flags
mov bx,argadr
mov [bx].flgs,al ; update flags in arg block
ret ; and return to caller
term endp
savescr proc near
push es ; move ds base address to es
push ds
pop es
mov di,offset scrsav ; point to start of screen save area
mov si,scnstrt ; point to screen memory area
mov cx,scnwrds ; setup word count
push ds
xor ax,ax ; point to base page with ds
mov ds,ax
cld
rep movsw ; transfer image to save area
pop ds ; restore registers and return
pop es
ret
savescr endp
restscr proc near
mov dx,offset curoff ; turn off cursor
mov ah,prstr
int dos
mov dx,offset blank ; clear screen to get rid of cursor
mov ah,prstr
int dos
push es ; point to base page with es
xor ax,ax ; restore screen
mov es,ax
mov di,scnstrt ; point to screen memory area
mov si,offset scrsav ; point to start of screen save area
mov cx,scnwrds ; setup word count
cld
rep movsw ; transfer image to screen
pop es
mov dx,offset curon ; turn on cursor
mov ah,prstr
int dos
ret
restscr endp
;; keyboard translator action routines, system dependent, called from msugen.
; These are invoked by a jump instruction. Return carry clear for normal
; processing, return carry set for invoking Quit (kbdflg has transfer char).
;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
;
chrout: call outprt ; put char in al to serial port
clc ; stay in Connect mode
ret
trnprs: push ax ; toggle Copy screen to printer
test ourarg.flgs,prtscr ; are we currently printing?
jnz trnpr2 ; nz = yes, its on and going off
mov ah,ioctl
mov al,7 ; get output status of printer
push bx
mov bx,4 ; file handle for system printer
int dos
pop bx
jc trnpr1 ; c = printer not ready
cmp al,0ffh ; Ready status?
je trnpr2 ; e = Ready
trnpr1: call beep ; Not Ready, complain
jmp trnpr3 ; and ignore request
trnpr2: xor ourarg.flgs,prtscr ; flip the flag
trnpr3: pop ax
clc
ret
klogon proc near ; resume logging (if any)
test flags.capflg,logses ; session logging enabled?
jz klogn ; z = no, forget it
or ourarg.flgs,capt ; turn on capture flag
klogn: clc
ret
klogon endp
klogof proc near ; suspend logging (if any)
and argadr.flgs,not capt ; stop capturing
klogo: clc
ret
klogof endp
snull: mov ah,0 ; send a null
call outchr ; send without echo or logging
nop
nop
nop
clc
ret
kdos: mov al,'P' ; Push to DOS
jmp short cmdcom
cstatus:mov al,'S' ; these commands exit Connect mode
jmp short cmdcom
cquit: mov al,'C'
jmp short cmdcom
cquery: mov al,'?'
jmp short cmdcom
cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
stc ; say exit Connect mode
ret
; 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