home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix CD 2.0
/
Phoenix_CD.cdr
/
01e
/
msk230s2.zip
/
MSXGEN.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-02-12
|
39KB
|
981 lines
name msxgen
; File MSXGEN.ASM
; Generic MS DOS Kermit module, does i/o via DOS calls.
; Use with file MSUGEN.ASM (Generic keyboard translator)
;
; Last edit: 8 Jan 1988
; 8 Jan 1988 Update 8 bit display in outtty. [jrd]
; 1 Jan 1988 version 2.30
; 10 Dec 1987 Add Showmodem command.
; 12 Sept 1987 version 2.30
; 18 July 1987 Remove redundant rxtable test (Tnx to Jack Bryans), pass all
; incoming serial port chars (except flow control) when Debug is on. [jrd]
; 25 May 1987 add keyboard translator, input translation, cleanups. [jrd]
; 1 Oct 86 Version 2.29a
; 30 Sept 1986 Reject DEL char at serial port reception level to avoid
; problems when DEL is used as a filler char (by Emacs). [jrd]
; 27 Sept 1986 Revise procedure Term to permit capturing, printer ready
; testing, debug display. Revised other port procedures slightly too;
; especially to set port into binary mode via ioctl. [jrd]
; 4 Sept 1986 Add Bob Goeke's change to move comms port table to a system
; dependent module (typ msx---) to allow 3+ ports and localized idents. [jrd]
; 26 May 1986 Make default display mode be Serial. [jrd]
;
; Note: the biggest difficulty using this Generic Kermit is loss of one
; or two incoming characters when the screen must scroll. IBM PC's and
; relatives do this. If possible, replace the DOS screen write with faster
; calls specific to your system. Procedure Sleep call (uses system time of
; day clock) is commented out below for systems lacking such a clock. [jrd]
public serini, serrst, clrbuf, outchr, coms, vts, vtstat, dodel
public ctlu, cmblnk, locate, lclini, prtchr, dobaud, clearl
public dodisk, getbaud, beep, trnprs, pcwait, shomodem, termtb
public count, xofsnt, puthlp, putmod, clrmod, poscur
public sendbr, sendbl, term, machnam, setktab, setkhlp, showkey
public ihosts, ihostr, dtrlow, serhng, dumpscr, comptab
public chrout, cstatus, cquit, cquery, chang ; kbd action verbs
public snull, kdos, klogof, klogon
include mssdef.h
false equ 0
true equ 1
instat equ 6
print_out equ 05h ; dos function to print to printer
prtscr equ 80h ; print screen pressed
; 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.
datas segment public 'datas'
extrn drives:byte,flags:byte, trans:byte
extrn portval:word, port1:byte, port2:byte, port3:byte, port4:byte
extrn comand:byte, dmpname:byte ; [jrd]
extrn kbdflg:byte, rxtable:byte
machnam db 'Generic MS-DOS 2.0$'
erms20 db cr,lf,'?Warning: System has no disk drives$'
erms40 db cr,lf,'?Warning: Unrecognized baud rate$'
erms41 db cr,lf,'?Warning: Cannot open com port$'
erms50 db cr,lf,'Error reading from device$'
hnd1 db cr,lf,'Enter a file handle. Check your DOS manual if you are '
db cr,lf,'not certain what value to supply (generally 3).$'
hnd2 db cr,lf,'Handle: $'
hnderr db cr,lf,'Warning: Handle not known.'
deverr db cr,lf,'Any routine using the communications port will'
db cr,lf,'probably not work.$'
hndhlp db cr,lf,'A one to four digit file handle $'
dev1 db cr,lf,'Device: $'
devhlp db cr,lf,'Name for your systems auxiliary port $'
badbd db cr,lf,'Unimplemented baud rate$'
noimp db cr,lf,'Command not implemented.$'
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,'$'
msmsg1 db cr,lf,' Communications port is not ready.$'
msmsg2 db cr,lf,' Communications port is ready.$'
rdbuf db 80 dup (?) ; temp buf [jrd]
shkmsg db 'Not implemented.'
shklen equ $-shkmsg
setktab db 0
setkhlp db 0
crlf db cr,lf,'$'
delstr db BS,BS,' ',BS,BS,'$' ; Delete string
; If delete code moves cursor then BS over code, BS over bad char, space
; over both to erase from screen, BS twice to restore cursor position.
clrlin db cr,'$' ; Clear line (just the cr part).
clreol db '^U',cr,lf,'$' ; Clear line.
telflg db 0 ; non-zero if we're a terminal.
argadr dw ? ; address of arg blk from msster.asm
parmsk db ? ; 8/7 bit parity mask, for reception
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
xofsnt db 0 ; Say if we sent an XOFF.
xofrcv db 0 ; Say if we received an XOFF.
count dw 0 ; Number of chars in int buffer.
prthnd dw 0 ; Port handle.
prttab dw com1,com2
com1 db 'COM1',0
com2 db 'COM2',0
tmp db ?,'$'
temp dw 0
temp1 dw ? ; Temporary storage.
temp2 dw ? ; Temporary storage.
prtstr db 20 dup(?) ; Name of auxiliary device
; Entries for choosing communications port
comptab db 6 ; Number of options
mkeyw '1',1
mkeyw '2',2
mkeyw 'COM1',1
mkeyw 'COM2',2
mkeyw 'Device',3
mkeyw 'File-handle',4
ourarg termarg <>
termtb db tttypes ; entries for Status, not Set
mkeyw 'Heath-19',ttheath
mkeyw 'none',ttgenrc
mkeyw 'Tek4014',tttek
mkeyw 'VT102',ttvt100
mkeyw 'VT52',ttvt52
datas ends
code segment public 'code'
extrn comnd:near, dopar:near, prserr:near, atoi:near, prompt:near
extrn sleep:near, msuinit:near, keybd:near
assume cs:code,ds:datas
; 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 ; Get number of drives in AL.
mov drives,al
ret
DODISK 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.
; Do nothing since we are not interrupt driven. Returns normally.
CLRBUF PROC NEAR ; rewritten by [jrd]
cmp prthnd,0 ; got a port handle yet?
jne clrbu1 ; ne = yes
ret ; else just return
clrbu1: call prtchr ; read from comms port
jmp clrbu1 ; returns when data available
nop
ret ; skip returns on no data
CLRBUF ENDP
; Clear to the end of the current line. Returns normally.
CLEARL PROC NEAR
push ax
push dx
mov ah,prstr
mov dx,offset clreol
int dos
pop dx
pop ax
ret
CLEARL ENDP
shomodem proc near
mov ah,cmcfm ; get a confirm
call comnd
jmp r ; no confirm
nop
cmp prthnd,0 ; Got a handle yet?
jne shmod0 ; Yup just go on
call opnprt ; Else 'open' the port
shmod0: mov dx,offset msmsg1 ; say port is not ready
mov bx,prthnd
mov al,7 ; output status command
mov ah,ioctl ; ask DOS to look for us
int dos
jc shmod1 ; c = call failed, device not ready
or al,al
jz shmod1 ; not ready...
mov dx,offset msmsg2 ; say port is ready
shmod1: mov ah,prstr
int dos
jmp rskp
shomodem 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 PROC NEAR
push cx ; save regs
or ah,ah ; sending a null?
jz outch2 ; z = yes
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: push dx ; Save register.
mov al,ah ; Parity routine works on AL.
call dopar ; Set parity appropriately.
; Begin revised output routine
mov byte ptr temp,al ; put data there
cmp prthnd,0 ; Got a handle yet?
jne outch3 ; Yup just go on
call opnprt ; Else 'open' the port
outch3: push bx
mov bx,prthnd ; port handle
mov cx,1 ; one byte to write
mov dx,offset temp ; place where data will be found
mov ah,write2 ; dos 2 write to file/device
int dos
pop bx ; end of revised routine
pop dx
pop cx
jmp rskp
OUTCHR ENDP
; This routine blanks the screen. Returns normally.
CMBLNK PROC NEAR
push ax ; save some registers
push dx
mov ah,prstr
mov dx,offset crlf ; carriage return plus line feed.
pop dx
pop ax
ret
CMBLNK ENDP
; Homes the cursor. Returns normally.
LOCATE PROC NEAR
mov dx,0 ; Go to top left corner of screen.
jmp poscur
LOCATE ENDP
; Write a line 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,1800h ; now address line 24
call poscur
pop dx ; get message back
mov ah,prstr
int dos ; write it out
ret ; and return
putmod endp
; clear the mode line written by putmod. Returns normally.
clrmod proc near
mov dx,1800h
call poscur ; Go to bottom row.
call clearl ; Clear to end of line.
ret
clrmod endp
; Put a help message on the screen.
; Pass the message in ax, terminated by a null. Returns normally.
puthlp proc near
push dx ; save regs
push si
push ax ; preserve this
mov ah,prstr
mov dx,offset crlf
int dos
pop si ; point to string again
cld
puthl3: lodsb ; get a byte
cmp al,0 ; end of string?
je puthl4 ; yes, stop
mov dl,al
mov ah,dconio
int dos ; else write to screen
jmp puthl3 ; and keep going
puthl4: mov ah,prstr
mov dx,offset crlf
int dos
pop si
pop dx
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 ah,prstr
mov dx,offset noimp ; Say it's not implemented.
int dos
push bx ; save reg
mov bx,portval
mov [bx].baud,0FFFFH ; So it's not a recognized value.
pop bx
ret ; Must be set before starting Kermit.
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
ret ; Can't do this.
GETBAUD ENDP
; Use for DOS 2.0 and above. Check the port status. If no data, skip
; return. Else, read in a char and return.
; Note added by [jrd]: The test for char-at-input-port is int 21h function
; 44h (ioctl) sub function 6 (get input status). On many systems an FFH will
; be reported (meaning Ready) even though no char is available; the Ready
; indication is misleading. In such cases the system will wait for a char
; and will appear to be hung. A preferrable method is to use the ROM Bios
; call int 14H function 3 (get port status) and if the lsb of the returned
; 8 bits in AH is 1 then a char is availble at the port; this assumes that
; the machine emulates this ROM Bios operation.
; Lastly, if the current code is used and the system hangs then reboot
; and say ECHO Hello >COM1 before running Kermit; this should make MSDOS
; truely aware of the port's actual status. Dark grey magic. Good luck! [jrd]
PRTCHR PROC NEAR
push bx
push cx
cmp prthnd,0 ; Got a handle yet?
jne prtch0 ; Yup just go on
call opnprt ; Else 'open' the port
prtch0: call chkxon
mov bx,prthnd
mov al,instat ; input status command
mov ah,ioctl ; see note above
int dos
jc prtch4 ; c = call failed, device not ready
or al,al
jz prtch4 ; not ready...
mov bx,prthnd ; the file handle
mov ah,readf2 ; read file/device
mov cx,1 ; want just one character
mov dx,offset rdbuf ; where to store it
int dos
jnc prtch1 ; nc = no error
cmp al,5 ; Error condition.
je prt3x
cmp al,6 ; Error condition
je prt3x
jmp prtch4 ; else report no char present.
prtch1:;;;mov count,0 ; update count (always 0 for one char reads)
mov dx,ax ; needed to obey rules
or ax,ax ; reading from end of file?
jz prtch4 ; z = yes
mov al,rdbuf ; recover char
prtch3: pop cx
pop bx
ret ; return success (char is in al)
prt3x: mov ah,prstr
mov dx,offset erms50
int dos
prtch4: pop cx
pop bx
jmp rskp ; no chars...
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
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
; 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
mov ax,1 ; sleep for 1 second
; NOTE: for systems with a time-of-day clock uncomment the line below
; (call sleep) to provide an interval for the host to respond.
;;; call sleep ; procedure sleep is in msscom.asm
call prtchr ; check for char at port
jmp ihosts1 ; have a char in al, repeat wait/read cycle
nop ; prtchr does skip return on empty 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 = null
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
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
; Send a break out the current serial port. Returns normally.
SENDBR PROC NEAR ; Normal Break
ret
SENDBR ENDP
SENDBL PROC NEAR ; Long Break
ret
SENDBL ENDP
; Position the cursor according to contents of DX:
; DH contains row, DL contains column. Returns normally.
POSCUR PROC NEAR
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
mov dx,offset comptab ; the table to examine
mov bx,0 ; use keywords as help
mov ah,cmkey ; parse keyword from comptab
call comnd
jmp r ; no match
push bx ; value following the located keyword
mov ah,cmcfm
call comnd ; Get a confirm.
jmp comx ; Didn't get a confirm.
nop
pop bx
cmp bl,3 ; Do they want to set device name?
je coms3 ; e = Yes go get name
jg coms4 ; g = pick up file handle
mov flags.comflg,bl ; Set the comm port flag.
cmp bl,1 ; Using Com 1?
jne coms2 ; Nope.
mov portval,offset port1
ret
coms2: cmp flags.comflg,2 ; using Com2?
jne coms3 ; ne = no
mov portval,offset port2
ret
comx: pop bx
ret
coms3: mov dx,offset dev1 ; Let user supply device name.
call prompt
mov ah,cmtxt ; parse string, returns asciiz string
mov bx,offset prtstr ; Put name here
mov dx,offset devhlp ; help message if user types question mark
call comnd
jmp coms31 ; Did user type ^C.
nop
mov comand.cmstat,cmcfm ; simulate a confirm has been requested
mov dx,offset prtstr ; Point to string
mov ah,open2 ; Open port as a file
mov al,2 ; For reading and writing
int dos
jc coms31 ; c = failure
mov portval,offset port3 ; port info structure
mov flags.comflg,3 ; set port ident
jmp short coms32 ; Success
coms31: mov ah,prstr
mov dx,offset erms41
int dos
mov dx,offset deverr
int dos
ret
coms32: mov prthnd,ax ; Save handle.
mov ah,ioctl
mov al,00h ; get device info
xor dx,dx
mov bx,prthnd ; port's handle
int dos
jc coms41 ; c = error
or dl,20h ; set binary mode in device info
mov dh,0
mov ah,ioctl
mov al,01h ; set device info
int dos
jc coms41 ; c = error
ret
coms4: mov dx,offset hnd2 ; Let user supply file handle.
call prompt
mov ah,cmtxt
mov bx,offset rdbuf ; Where to put input.
mov dx,offset hndhlp ; In case user wants help.
call comnd
jmp coms41 ; No go.
nop
cmp ah,4 ; Right amount of data?
ja coms41 ; Too many chars.
mov comand.cmstat,cmcfm ; simulate a confirm has been requested
mov si,offset rdbuf
call atoi ; Convert to real number in ax
jmp coms41 ; Keep trying.
nop
mov portval,offset port4 ; port info structure
mov flags.comflg,4 ; set port ident
jmp coms32 ; go complete processing
coms41: mov ah,prstr ; Else, issue a warning.
mov dx,offset hnderr
int dos
ret ; Yes, fail.
COMS ENDP
; Set heath emulation on/off.
VTS PROC NEAR
jmp notimp
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
ret
DUMPSCR ENDP
notimp: mov ah,prstr
mov dx,offset noimp
int dos
jmp prserr
; Initialize variables to values used by the generic MS DOS version.
lclini: mov flags.vtflg,0 ; Don't to terminal emulation.
mov prthnd,0 ; No handle yet
mov flags.remflg,dserial ; set serial display mode
;; call opnprt ; Get file handle for comm port.
call msuinit ; declare keyboard translator present
ret
; Get a file handle for the communications port. Use DOS call to get the
; next available handle. If it fails, ask user what value to use (there
; should be a predefined handle for the port, generally 3). The open
; will fail if the system uses names other than "COM1" or "COM2".
opnprt: mov al,flags.comflg
dec al ; com1 is 1, com2 is 2, etc
mov ah,0
push si
mov si,ax
shl si,1 ; double index
mov dx,prttab[si] ; table of port names
pop si
mov ah,open2 ; open file/device
mov al,2 ; for reading/writing
int dos
jnc opnpr2 ; nc = no error so far
mov ah,prstr ; It didn't like the string.
mov dx,offset erms41
int dos
mov dx,offset hnd1
int dos
opnpr0: mov dx,offset hnd2 ; Ask user to supply the handle.
call prompt
mov ah,cmtxt
mov bx,offset rdbuf ; Where to put input.
mov dx,offset hndhlp ; In case user wants help.
call comnd
jmp opnpr3 ; Maybe user typed a ^C.
nop
mov si,offset rdbuf
call atoi ; Convert to real number
jmp opnpr0 ; Keep trying.
nop
mov prthnd,ax ; Value returned in AX
ret
opnpr2: mov prthnd,ax ; Call succeeded.
mov ah,ioctl
mov al,00h ; get device info
xor dx,dx
mov bx,prthnd ; port's handle
int dos
or dl,20h ; set binary mode in device info
mov dh,0
mov ah,ioctl
mov al,01h ; set device info
int dos
ret
opnpr3: cmp flags.cxzflg,'C' ; Did user type a ^C?
jne opnpr4 ; No, don't say anything.
mov ah,prstr ; Else, issue a warning.
mov dx,offset hnderr
int dos
opnpr4: ret ; Yes, fail.
showkey:
mov ax,offset shkmsg
mov cx,shklen
ret
; Initialization for using serial port. Returns normally.
; Attempts to put port device in binary mode. [jrd]
SERINI PROC NEAR
cld ; Do increments in string operations
cmp prthnd,0 ; Got a handle yet?
jne serin0 ; ne = yes, just go on
push bx
call opnprt ; Else 'open' the port
pop bx
serin0:;;;; call clrbuf ; Clear input buffer.
push bx
mov bx,portval ; get port
mov parmsk,0ffh ; parity mask, assume parity is None
cmp [bx].parflg,parnon ; is it None?
je serin1 ; e = yes
mov parmsk,07fh ; no, pass lower 7 bits as data
serin1: mov bx,[bx].flowc ; get flow control chars
mov flowoff,bl ; xoff or null
mov flowon,bh ; xon or null
pop bx
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
; Produce a short beep. The PC DOS bell is long enough to cause a loss
; of data at the port. Returns normally.
BEEP PROC NEAR
mov dl,bell
mov ah,dconio
int dos
ret
BEEP ENDP
;
; Dumb terminal emulator. Doesn't work too well above 1200 baud (and
; even at 1200 baud you sometimes lose the first one or two characters
; on a line). Does capture (logging), local echo, debug display, tests
; for printer/logging device not ready. Uses keyboard translator
; 20 March 1987 [jrd].
term proc near
mov argadr,ax ; save argument ptr
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
cld
rep movsb ; copy into our arg blk
and ourarg.flgs,not (prtscr) ; no screen printing at startup
mov ax,ourarg.captr
mov captrtn,ax ; buffer capture routine
mov parmsk,0ffh ; parity mask, assume parity = None
cmp ourarg.parity,parnon ; is parity None?
je term1 ; e = yes, keep all 8 bits
mov parmsk,07fh ; else keep lower 7 bits
term1: call portchr ; get char from port, apply parity mask
jnc short term2 ; nc = no char, go on
call outtty ; display and capture char
jmp term1 ; do quick loop back for more
term1b: call outtty ; display and capture char
term2: call keybd ; keyboard translator to read and send text
jnc term1 ; nc = do not exit Connect mode
term4: ret
term 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 exit Connect mode (kbdflg has transfer char).
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
chang: mov al,'H' ; Hangup, drop DTR & RTS
;;; jmp short cmdcom
cmdcom: mov kbdflg,al ; pass char to msster.asm via kbdflg
stc ; say exit Connect mode
ret
;; end of action routines
; 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
mov bx,offset rxtable ; address of translate table
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)?
jne outnp5 ; ne = no
jmp beep ; use short beep, avoid char loss.
outnop1:
outnp5: test flags.remflg,d8bit ; keep 8 bits for displays?
jnz outnp9 ; nz = yes, 8 bits if possible
and al,7fh ; remove high bit
outnp9: 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.
; Can send an 8 bit char while displaying only 7 bits locally.
outprt proc near
test ourarg.flgs,lclecho ; echoing?
jz outpr1 ; z = 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
nop
portc0: clc ; no carry -> no character
ret ; and return...
portc1: and al,parmsk ; apply 8/7 bit parity mask
or al,al ; catch nulls
jz portc0 ; z = null, ignore it
cmp al,del ; catch dels
je portc0 ; e = del, ignore it
portc2: stc ; have a character
ret ; and return
portchr 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