home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
modem
/
term.arc
/
TERM.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-02-07
|
34KB
|
1,327 lines
;
; vi:set ts=8:
;
TITLE terminal program
;
; This is version 2.2 of TERM. TERM is a terminal program that
; emulates a zenith z19 terminal. It's main feature is, that it is
; memory-resident. This allows you to run two tasks simultaneouly,
; one on your dos machine, the other on the host computer.
; You can switch easily back and forth by pressing the hotkey.
; TERM has a 2048 character receive buffer, and receives characters
; while you are doing other things under Dos. The characters are
; printed on the screen, when you switch back to the host.
; When term receives the bell character, while it's in the
; background, it will switch immediately to the foreground.
; Thus, you are notified if you receive mail (biff) or
; someone wants to talk with you
;
; Mail problems, suggestions or bug reports to:
;
; Karl Gegenfurtner
;
;arpa: karl@hipl.psych.nyu.edu
;uucp {ihnp4|seismo|allegra}!cmcl2!xp!hipl!karl
;usps: New York University
; Dept. of Psychology
; 6 Washington Place 8th floor
; New York, NY 10003
;
; In the case, that you make major improvements to term,
; like adding file transfer capabilities, I really would
; want to get copy of the program, before you sell it.
;
; History:
; - fall 1986: Version 1.0 by Hans Irtel, Uni Regensburg
; output is via ansi driver int 29h
; send xoff/xon when switching
; - spring 87: Version 2.0 by Karl Gegenfurtner, New York University
; added z19 emulation
; rewrote the comm-initialization routines
; made the dos interface well-behaved
; put xon/xoff into interrupt routine
; - april 87: Version 2.1 Wed Apr 01 18:35:05 1987
; added alarm feature
; added support for monochrome card
; - april 87: Version 2.2 Thu Apr 02 19:12:39 1987
; dynamically allocate rxbuffer to reduce prog size
; fix cexit bug (restore comm int)
; fix the monochrome cursor
; add keypad enter pseudo sequences for xp
; moved cinit and cexit to non-resident part
; made some equates to variables for install
; fix the silly bug in kb_int, which caused two
; instances of term running simultaneously
; Wed Apr 08 20:06:07 1987
; fixed init code in enab
;
;
; Future:
; - write installation program
; - add some primitive functions for reinitializing etc.
;
;
;
; installation equates
;
Ifgcolor equ 74h
Ibgcolor equ 47h
Iswitchcode equ 3400h ; 3400h is F12 on an AT
; 4400 is F10 on a PC
; 7000 is alt-f9 on a PC
Itport equ 2 ; comm port to use
Iline_par equ 11100011b
; comm line parameters
; 8 data bits, 1 stopbit, no parity
logo equ "HI" ; for Hans Irtel
terminal_page equ 1 ; alternate video page
show_ctrl equ 0 ; show ctrl chars as ^x
;
; other useful defines
;
xon equ 11h
xoff equ 13h
eoi equ 20h ; non-specific eoi
c1mask equ 0efh
c2mask equ 0f7h
c1off equ 10h
c2off equ 08h
c1base equ 03f8h
c2base equ 02f8h
c1int equ 0ch
c2int equ 0bh
int_enable equ 1
line_control equ 3
modem_control equ 4
line_status equ 5
buflen equ 2048
maxcount equ buflen-64
lowcount equ 128
chesc equ 27
bel equ 7
cr equ 13
lf equ 10
bs equ 8
tab equ 9
screen equ 10h ; bios screen call
screensize equ 25*80
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
code_seg segment
assume cs:code_seg, ds:code_seg, es:code_seg
org 100H
terminal proc far
jmp install
terminal endp
;
; the first data may be changed by the installation program
;
fgcolor DB Ifgcolor
bgcolor DB Ibgcolor
tport DW Itport
line_par DB Iline_par
switchcode DW Iswitchcode
;
; data for routines
;
old_com1 DW 00H
old_com2 DW 00H
kb_bios label dword
old_kb1 DW 00H
old_kb2 DW 00H
rxbuffer DW offset lastbyte
buf_end DW offset lastbyte + buflen
head DW offset lastbyte
tail DW offset lastbyte
tflag DB 0
alarm DB 0
bw DB 0
count DW 0
txoff DB 0
rxoff DB 0
rxfull DB 0
cbase DW 0
cmask DB 0
coff DB 0
cint DB 0
freemem DW offset lastbyte + buflen
usersave DW offset lastbyte + buflen + 2
termsave DW offset lastbyte + buflen + 2 + screensize * 2
mofreemem DW offset lastbyte + buflen + 2 + screensize * 2 * 2
usercursor DW 0
termcursor DW 0
;
; stuff for screen routines
;
trnctl equ 80h
lnwrap equ 40h ; line wrap enabled.
line25 equ 20h
IF show_ctrl
flags db 0C0h
ELSE
flags db 40h ; status flags...
ENDIF
cursor dw 0
esc_ch db ?
argadr dw ? ; address of arg blk
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'
db 'jk'
db 'xy'
db '>='
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
dw savecur,restcur
dw smarg, rmarg
dw escign, escign
coord dw ?
insmod db ?
wcoord dw ?
ttstate dw offset scrini
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 80
crt_lins db 24
crt_page db 0
low_rgt dw ? ; lower right corner of window
oldcur dw 0 ; save'd cursor position
;---------------------------------------------------------------------
; communication interface routines:
; cinit: initialize interrupts of port in dx
; cgetch: get next charcacter from buffer to al
; cputch: put character in al out on comm port
; cexit: reset interrupts
; rxchar: interrupt service routine
;----------------------------------------------------------------------
;
; interface routines
;
; cinit moved to non-resident part
;
; second entry point just for a re-init
;
enab proc near
;
; set up the serial card
;
mov dx, cbase
add dx, line_control
mov al, 3
out dx, al
mov dl, 0f8h
in al, dx
;
; start RS232 interrupt
;
mov dx, cbase
add dx, int_enable
mov al, 1
out dx, al
mov dl, 0fch
mov al, 0fh
out dx, al
;
; set up 8259 interrupt controller
;
cli
in al, 21H
and al, cmask
out 21H, al
sti
;
; done
;
ret
enab endp
;
; cexit moved to the non-resident part
;
cgetch proc near
cmp count, 0
je gc3
mov bx, head
mov al, [bx]
inc bx
cmp bx, buf_end
jne gc1
mov bx, rxbuffer
gc1: mov head, bx
cli ; no interrupts during change of count
dec count
sti
;
; check for leaving buffer full state
;
test rxfull, 80h
jz gc2
;
; we are in rxfull state
;
cmp count, lowcount
ja gc2
;
; buffer is free to receive new charcters now
;
push ax
mov ax, xon ; send XON protocol
call txchar
mov rxfull, 0
mov rxoff, 0
pop ax
gc2: mov ah, 0
ret
gc3: mov ax, -1
ret
cgetch endp
cputch proc near
test txoff, 80h
jnz t0
call txchar ; character in al
jmp t1
;
; in txoff state: return without sending
;
t0: mov ax, -1
t1: ret
cputch endp
txchar proc near
mov ah, al; save character
mov dx, cbase
add dx, line_status
tx1: in al, dx
test al, 20h; wait for THRE
jz tx1
;
; ready to transmit
;
sub dx, line_status; point to THR
mov al,ah
out dx, al
mov ah, 0
ret
txchar endp
rxchar proc far
push ax
push bx
push dx
push ds
mov ax, cs
mov ds, ax
mov dx, cbase
in al, dx
cmp al, xoff
jne r1
;
; XOFF found
;
mov txoff, 80h; set TXOFF state
jmp short rxreturn
r1: cmp al, xon
jne r2
;
; XON found
;
mov txoff, 0; clear TXOFF state
jmp short rxreturn
;
; insert character into rxbuffer
;
r2: mov bx, tail
mov [bx], al
inc bx
cmp bx, buf_end
jne r3
mov bx, rxbuffer
r3: mov tail, bx
inc count
;
; check for attention charcter
;
test cs:tflag, 80h
jnz r4
;
; we are in background mode
;
and al, 127
cmp al, 7h
jnz r4
mov cs:alarm, 80h
r4: cmp count, maxcount
jbe rxreturn
; rxbuffer full
mov rxfull, 80h; set rxfull state
mov ax, xoff
call txchar
rxreturn:
; clear interrupt controller
cli ; int enabled by IRET instruction
mov al, eoi
mov dx, 20h
out dx, al
pop ds
pop dx
pop bx
pop ax
iret
rxchar endp
;--------------------------------------------------------------------
; screen routines: emulate a zenith z19 terminal
; only entry point here is outtty, which outputs the
; character given in al
;---------------------------------------------------------------------
;
; init: called automatically on startup
;
scrini proc near ; init screen stuff
push ax ; save character
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 crt_page, bh
mov ah, fgcolor
mov curattr,ah ; else set nice screen attribute
mov ttstate,offset outtt0 ; normal screen state
mov ah,3 ; figure out where cursor is
mov bh, crt_page
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
mov bh, crt_page
int screen ; set cursor in case it moved
pop ax
jmp outtty
scrini endp
outtty proc near
outnop1:mov dx,cursor ; these may need cursor...
and al, 127
cmp al, 0
jz outign
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: mov bh, crt_page ; 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 flags,lnwrap ; in wrap mode?
jz outign ; no, just return w/out updating cursor
wrap: xor dl,dl
inc dh ; handle wrap
setcur: cmp dh,crt_lins
jb setc1 ; not off end, keep going
push dx ; save row/col
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: mov bh, crt_page
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
add dl,8 ; tab is at most 8 columns
and dl,not 111b ; round down to a multiple of 8
cmp dl,crt_cols ; out of range?
jb setcur ; no, go set it
test flags,lnwrap ; in wrap mode?
jnz outta1 ; yes, wrap to next line
mov dl,byte ptr low_rgt ; else just move to right margin
jmp setcur
outta1: jmp wrap
; 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
escign: ret
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 bh,fgcolor ; always use foreground
; 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,fgcolor ; always use foreground
; 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 ah,7h ; scroll down.
mov bh,curattr ; attribute
cmp ch,dh ; moving last line down?
jne insli2 ; no, keep going
mov al,0 ; yes, just clear it
insli2: 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 ah,6h ; scroll up.
mov bh,curattr ; attribute
cmp ch,dh ; deleting last line?
jne delli2 ; no, go on
mov al,0 ; yes, just blank it
delli2: 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: ret
vtid1: ret
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 ah, bgcolor
mov curattr,ah ; attribute for inverse video
ret
nrmvid: mov ah, fgcolor
mov curattr,ah ; attribute for normal video
ret
dowrap: or flags,lnwrap ; turn on wrap mode
ret ; and return
nowrap: and flags,not lnwrap ; turn off wrap mode
ret ; and return
smarg: mov ttstate, offset setmo
ret
rmarg: mov ttstate, offset resetmo
ret
setmo: mov ttstate, offset outtt0
cmp al, '1'
je ena25
cmp al, '4'
je cblock
ret
resetmo:
mov ttstate, offset outtt0
cmp al, '1'
je disa25
cmp al, '4'
je cul
ret
ena25: test flags, line25
jnz en0 ; already set
mov dx, low_rgt
inc dh
mov low_rgt, dx
inc crt_lins
or flags, line25
en0: ret
disa25: test flags, line25
jz d0 ; aleady disabled
mov dx, low_rgt
dec dh
mov low_rgt, dx
dec crt_lins
and flags, not line25
d0: ret
cblock: mov ah, 1
test bw, 80h
jnz cbl1
mov cx, 0007h
jmp short cbl2
cbl1: mov cx, 000dh
cbl2: int screen
ret
cul: test bw, 80h
jnz cul1
mov cx, 0607h
jmp short cul2
cul1: mov cx, 0c0dh
cul2: mov ah, 1
int screen
ret
; 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
; save cursor
savecur:
mov oldcur,dx
ret
; restore cursor
restcur:
mov dx,oldcur
jmp setcur
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 ah, crt_page
mov al, 0
add ax, 0b000h
cmp crt_mode,7 ; 7 is bw (***)
je scrse1
add ax, 800h ; 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
;----------------------------------------------------------------------
; keyboard interrupt routines: check for alarm flag
; and switch-code
;----------------------------------------------------------------------
;
; start of the main routines
;
slogo DW logo
kb_int proc far
;
; first we check for an alarm, in that case we call main immediately
; note that alarm only happens when running in background
; then we check for a read, the case we don't check for a kb-status
; is, that the status uses the flags to return values and
; modifying the users flags on the stack would mess up our
; routines (too much overhead)
;
; rearrange these routines in the next version
; when a read is interrupted by term, we should check
; the keyboard until a key is pressed before actually
; going into the read again.
;
sti
test cs:alarm, 80h
jz kbx
mov cs:alarm, 0
test cs:tflag, 80h ; there is a silly condition here
jnz kbx
call main
kbx: cmp ah, 0
jz kb0
jmp cs:[kb_bios]
kb0: pushf
call cs:[kb_bios]
cmp ax, cs:switchcode
jne kb1
test cs:tflag, 80h
jnz kb1
call main
mov ah, 0
jmp kb0
kb1: iret
kb_int endp
;-----------------------------------------------------------------
; main program: just loop to get input from the keyboard
; and the comm-port, and output it to the other ends
;-----------------------------------------------------------------
main proc near
;
; save registers
;
push ax
push bx
push cx
push dx
push ds
push es
push di
push si
push bp
mov ax, cs
mov ds, ax
mov es, ax
mov tflag, 80h
;
; restore the last environment
;
test bw, 80h
jz e0
;
; first save the users current screen
;
mov di, usersave
mov cx, screensize
mov ax, 0b000h
mov ds, ax
mov si, 0
rep movsw
push cs
pop ds
;
; now restore terminals last screen
;
mov si, termsave
mov cx, screensize
mov ax, 0b000h
mov es, ax
mov di, 0
rep movsw
push cs
pop es
;
; now also save the cursor
;
mov ah, 3
mov bh, 0
int screen
mov usercursor, dx
mov ah, 2
mov dx, termcursor
int screen
jmp m0
;
; switch video page
;
e0: mov ax, 0500h + terminal_page
int screen
;
; main loop
;
m0: mov ah, 1
int 16h
jz m1
mov ah, 0
int 16h
;
; check keyboard input for switch character
;
cmp ax, switchcode
je mexit
;
; translate del into destructive backspace
;
cmp ah, 83
jne m00
mov al, 127
;
; send character out
;
m00: call cputch
;
; check rxbuffer
;
m1: cmp count, 0
je m0
call cgetch
call outtty
jmp m0
;
; return to dos task, first clear rxbuffer
;
mexit: cmp count, 0
je mdone
call cgetch
call outtty
jmp mexit
mdone:
;
; save the current environment
;
test bw, 80h
jz e2
;
; first save terms current screen
;
mov di, termsave
mov cx, screensize
mov ax, 0b000h
mov ds, ax
mov si, 0
rep movsw
push cs
pop ds
;
; now restore the users last screen
;
mov si, usersave
mov cx, screensize
mov ax, 0b000h
mov es, ax
mov di, 0
rep movsw
push cs
pop es
;
; now also restore the cursor
;
mov ah, 3
mov bh, 0
int screen
mov termcursor, dx
mov dx, usercursor
mov ah, 2
int screen
jmp e3
e2: mov ax, 0500h
int 10h
;
; done, restore registers
;
e3: mov tflag, 0
pop bp
pop si
pop di
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
ret
main endp
;-------------------------------------------------------------------
; installation/uninstallation routines
;-------------------------------------------------------------------
;
even
lastbyte label byte
;
; only once
;
cinit proc near
;
; initialize buffer
;
mov ax, rxbuffer
mov head, ax
mov tail, ax
xor ax, ax
mov count, ax
;
; clear state flags
;
mov txoff, al; transmitting allowed
mov rxfull, al; buffer empty
mov rxoff, al; no XOFF sent
;
; set the interrupt vector to our routine
;
cmp dx, 1
jne c0
mov cmask, c1mask
mov coff, c1off
mov cint, c1int
mov cbase, c1base
jmp c1
c0: mov cmask, c2mask
mov coff, c2off
mov cint, c2int
mov cbase, c2base
c1: push es
mov ah, 35H
mov al, cint
int 21H
mov word ptr old_com1, bx
mov word ptr old_com2, es
pop es
push ds
mov dx, offset rxchar
mov ah, 25h
mov al, cint
push cs
pop ds
int 21h
pop ds
call enab
ret
cinit endp
cexit proc near
;
; note: ds has to equal old installation segment on call
;
; disable rs232 interrupt
;
mov dx, cbase
add dx, modem_control
mov al, 3
out dx, al
mov dx, cbase
add dx, int_enable
mov al, 0
out dx, al
;
; disable com interrupts
;
cli
in al, 21h
or al, coff
out 21h, al
sti
;
; restore old vector
;
mov ah, 25h
mov al, cint
push ds
mov dx, old_com1
mov bx, old_com2
mov ds, bx
int 21h
pop ds
ret
cexit endp
install proc near
;
; hook up program
;
mov dx, offset copyr
mov ah, 09h
int 21h
mov tflag, 0 ; not running
mov ax, 3516h
int 21h
cmp es:slogo, logo
jnz inst1
jmp uninstall
;
; install
;
inst1: mov word ptr old_kb1, bx
mov word ptr old_kb2, es
;
; we have to check some stuff before changing vectors
;
;
; check for monochrome card
;
mov ah, 0fh
int screen
cmp al, 7
jz inst2
mov dx, 0
mov bh, terminal_page
mov ah, 2
int screen
mov ax, 0b800h + terminal_page * 100h
mov es, ax
mov di, 0
jmp inst3
;
; only a single page, allocate 2 more pages
;
inst2: mov bw, 80h
push cs
pop es
mov ax, mofreemem
mov freemem, ax
mov termcursor, 0
mov di, termsave
inst3: mov cx, screensize
mov ah, fgcolor
mov al, ' '
cld
rep stosw
push cs
pop es
;
; finally, get going
;
mov dx, offset kb_int
mov ax, 2516h
int 21h
;
; setup ints ( this should be taken from the command line)
;
mov ah, 0
mov al, line_par
mov dx, tport
dec dx
int 14h
inc dx
call cinit
;
; signon
;
mov dx, offset signon
mov ah, 9h
int 21h
mov dx, freemem
int 27h
install endp
;
uninstall proc near
;
; note: es holds segment of first installation
;
mov dx, es:old_kb1
mov cx, es:old_kb2
mov ax, 2516h
mov ds, cx
int 21h
push es
pop ds
call cexit
;
; free memory
; note: es still holds segment
; we also have to free the environment
;
push cs
pop ds
mov ah, 49h
int 21h
mov ax, word ptr es:[2ch]
mov es, ax
mov ah, 49h
int 21h
;
mov dx, offset clear
mov ah, 9h
int 21h
;
mov ax, 4c00h
int 21h
uninstall endp
copyr DB "HiTerm memory resident terminal program"
DB " Version 2.2 04-09-87", 13, 10
DB "Copyright (c) Hans Irtel & Karl Gegenfurtner"
DB 13, 10, 13, 10, "$"
signon DB "Terminal installed", 13, 10, "$"
clear DB "Exit from terminal", 13, 10, "$"
code_seg ends
end terminal