home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
sampler0
/
tt.asm
< prev
next >
Wrap
Assembly Source File
|
1988-02-21
|
21KB
|
848 lines
COMMENT * ==================================================================
Copyright (C) 1988, George A. Stanislav.
All Rights Reserved.
This program is a dumb terminal for FOSSIL communications.
It works only from the COM1 port and only at 300/1200/2400
baud, with a built-in ansi-bbs and AVATAR terminal emulation.
That means that if you call a BBS supporting ANSI graphics,
it should correctly recognize the movement of your cursor keys,
as well as the <home> and <end> keys. More importantly, if
the BBS sends out Opus color codes, the AVATAR emulator will
convert them to ANSI sequences. You need ANSI.SYS properly
installed for either emulation to work properly.
The purpose of this program is mostly didactical. Lesson 2
of FOSSIL programming. (Lesson 1 was the previous version,
called DUMBTERM.) You can probably add Lesson 3 as of version
1.02, the lesson is contained in the AVATAR emulator.
New in version 1.03 are 20 user configurable keys. With the
help of TTSETUP.COM, you can configure the 10 function keys
when combined with either <ctl> or <alt> for a string up to
32 characters long. The same program will allow you to choose
defaults other than those coded here.
While the program is a dumb terminal, it allows you to transfer
file using the Zmodem protocol. For that, however, you need
TWO additional programs: Author's PROZ.COM and Chuck Forsberg's
DSZ.COM or DSZ.EXE. Of the two, PROZ.COM must be in the current
default directory, while DSZ can be anywhere as long as the
PATH environmental variable is pointing at it.
You can freely copy it and give it to others. The word FREELY
is substantial. Any charge imposed in connection with passing
this program onto someone else is in direct violation with
my Copyright. That also means that anyone who sells diskettes
or other media with public domain or shareware programs is
expressly prohibited from distributing this program. This program
is NOT in public domain!
Usage:
As it is a very simple terminal indeed, all you need is
a 300, 1200, or 2400 baud modem attached to COM1 and
type TT.
Whatever you type thereafter goes directly into the
modem. To dial a number you will have to type
ATDT 123-4567 <cr>. To initialize the modem, you
will have to type ATZ or whatever your modem manual
suggests.
To exit the program, type ^END. That means you can use
^C online.
Obviously, you cannot use this program for file transfers. This
is just a dumb terminal.
Support form author:
None.
* ===========================================================================
; MACROS to make it look like a high level language
fossil macro ; call FOSSIL driver
int 14h
endm
dos macro ; call MS DOS
int 21h
endm
print macro text
mov ah,09h ; display string
ifnb <text>
mov dx,offset text ; point to it
endif
dos
endm
exit macro level
mov ax,4c00h + level ; ah = 4ch, al = level
dos
endm
port macro ; choose COM1
mov dx,cport ; dx = cport
fossil ; call the driver
endm
setB macro rate ; set baud rate
ifnb <rate>
mov al,baud ; that's ah = 0, al = 10000011 initially
endif
xor ah,ah
port ; COM1
endm
csend macro ; transmit a character from al
mov ah,1 ; the character must already be in al
port
endm
crec macro ; receive a character from fossil buffer
mov ah,2 ; the received character will be in al
port
endm
open macro
local opened,oldfos,done
mov ah,4 ; initialize fossil
port
cmp ax,1954h ; the fossil "magic" number
je opened ; achieved
print msg ; fossil not present
exit 1 ; abort with errorlevel 1
opened: cmp bh,4 ; need at least FOSSIL, rev. 4
jb oldfos
cmp bl,19h ; can we write a block?
jnb done ; yes, done
oldfos: add oldrev,bh ; fix error message
print neednew ; print error message
exit 2 ; abort with errorlevel 2
done:
endm
close macro ; cleanup
mov ah,5
port
endm
dtr macro onoroff
mov ax,600h + onoroff ; on = 1, off = 0
port
endm
finkey macro ; fossil "inkey"
mov ah,0ch
port
inc ax ; zero flag = 0 if nothing there
endm
inkey macro ; keyboard "inkey"
mov ah,0dh
fossil ; never mind the port
inc ax ; check zero flag
endm
cget macro ; read character from keyboard
mov ah,0eh
fossil
endm
cput macro ; display a character
mov ah,13h ; character must be in al
fossil
endm
sends macro string,strlen
ifnb <string>
mov di,offset string
mov cx,strlen
endif
mov ah,19h
fossil
endm
talk macro
local talk1,talked ; talk to the other end
inkey ; check if the keyboard has been hit
jz talked ; no it was not, keep quiet
cget ; yes, see what it is
or al,al ; is it a function key?
jne talk1 ; no, send it out
call funkey ; process function key
jmp short talked
talk1: csend ; send char out
talked:
endm
listen macro
local l1,listen1,listened ; listen to the other end
finkey ; anything there?
jz listened ; nope
crec ; receive character
cmp al,26 ; is it a control character?
ja listen1 ; no, check further
l1: call avatar ; advanced video attribute transfer
jmp short listened
listen1:cmp avaflag,0 ; are we processing avatar?
jne l1 ; yes, call avatar
cput ; no, display it
listened:
endm
chat macro
local keep
keep:
talk
listen
jmp keep
endm
sendc macro char
mov al,char
csend
endm
; DEFINES
ctlA equ 1
ctlB equ 2
ctlC equ 3
ctlD equ 4
ctlE equ 5
ctlF equ 6
ctlG equ 7
ctlH equ 8
ctlL equ 12
ctlV equ 22
ctlY equ 25
cr equ 13
dle equ 16
lf equ 10
bell equ 7
stop equ '$'
on equ 1
off equ 0
tab equ 9
bmask equ 00011111b ; baud rate mask
b3 equ 01000000b ; 300 baud mask
b12 equ 10000000b ; 1200 baud mask
b24 equ 10100000b ; 2400 baud mask
pmask equ 11100000b ; parity etc. mask
p7E1 equ 00011010b ; mask for 7E1
p8N1 equ 00000011b ; mask for 8N1
imask equ 00001000b ; intensity bit
fgrmask equ 00000111b ; foreground color mask
bkgmask equ 01110000b ; background color
black equ 0
blue equ 1
green equ 2
cyan equ 3
red equ 4
magenta equ 5
brown equ 6
white equ 7
vflag equ 1 ; ^v received
aflag equ 2 ; ^v^a received
yflag equ 3 ; ^y received
yflag2 equ 4 ; ^y received, repeat character known
hflag equ 5 ; ^v^h received
hflag2 equ 6 ; ^v^h received, row known
noflag equ 0
; The PROGRAM
dumb segment
assume ds:dumb,es:dumb,cs:dumb,es:dumb
org 100h
main proc
start: jmp begin
version dw 0104h ; 1.04
cport dw 0 ; start with COM1
baud db 10000011b ; start with 1200 baud 8N1
editor db 0,' /C ',80 dup(0) ; space for editor
macword label word
mac db 20 dup (32 dup (?)) ; space for 20 key macros
macount db 20 dup (0) ; sizes of 20 key macros
copr db cr,lf,'TinyTerm - ANSI & AVATAR Emulating Terminal, version 1.04',cr,lf
db 'Copyright (C) 1988, George A. Stanislav',cr,lf
db 'All Rights Reserved.',cr,lf,lf
db 'This is a very simple terminal. Whatever you type '
db '(except ^<end>) is sent',cr,lf
db 'straight to the modem. Its initial setup is 1200 baud, 8N1, from '
db 'COM1. The full',cr,lf
db 'assembly language source code is included so you can write '
db 'your own programs',cr,lf
db 'using other configurations. The goal of this program is to '
db 'show to as many',cr,lf
db 'as possible how to write FOSSIL communications programs '
db 'and AVATAR emulation.',cr,lf,lf
db 'TinyTerm allows you to configure the 10 function keys '
db 'combined with the',cr,lf
db '<alt> or <ctl> keys as "macros". You can either define '
db 'them in the source',cr,lf
db 'code or, better yet, by running TTSETUP.COM. This also '
db 'allows you to choose',cr,lf
db 'defaults other than COM1, 1200 baud and 8N1.',cr,lf,lf
db 'Hit <F10> for help, <Ctrl> <End> to exit.',cr,lf,lf,stop
msg db 'FOSSIL not found. In order to run this program you need to '
db 'load a FOSSIL',cr,lf
db 'communications driver before you call TINYTERM.',cr,lf,stop
neednew db cr,lf,lf,'You are using revision '
oldrev db '0 of FOSSIL. For TinyTerm to run properly you',cr,lf
db 'need revision 5 or higher.',cr,lf,lf,stop
help db cr,lf,lf,tab
db ' TinyTerm Help:',cr,lf,lf,tab
db '< F1 > - ATDT',cr,lf,tab
db '< F2 > - AT <return>',cr,lf,tab
db '< F3 > - AT',cr,lf,tab
db '< F4 > - 300 baud',cr,lf,tab
db '< F5 > - 1200 baud',cr,lf,tab
db '< F6 > - 2400 baud',cr,lf,tab
db '< F7 > - 7E1',cr,lf,tab
db '< F8 > - 8N1',cr,lf,tab
db '< F9 > - A/ ( = redial)',cr,lf,tab
db '<ctrl> or <alt> <F1 - F10> - user defined macros',cr,lf,tab
db '<alt> <H> - drop DTR [hang up]',cr,lf,tab
db '<alt> <R> - raise DRT',cr,lf,tab
db '<alt> <D> - drop to DOS temporarily',cr,lf,tab
db '<alt> <E> - call the editor',cr,lf,lf,tab
db 'The following file transfer commands need DSZ:',cr,lf,lf,tab
db '<PgDn> or <PgUp> - Zmodem receive/send',cr,lf,tab
db '<ctrl> <PgDn> or <ctrl> <PgUp> - Xmodem (CRC) transfer',cr,lf,lf,tab
db 'Hit <ctrl> <end> or <alt> <X> to exit',cr,lf,lf,stop
drop db cr,lf,lf,tab,'DTR dropped',cr,lf,lf,stop
raise db cr,lf,lf,tab,'DTR raised',cr,lf,lf,stop
zbad db cr,lf,lf,bell,tab,'For file transfer you need a copy of DSZ.COM or DSZ.EXE'
db cr,lf,tab,'somewhere on the path.',cr,lf,lf,stop
nocom db cr,lf,bell,tab,'COMSPEC not found.',cr,lf,stop
command db 80 dup(0)
cmdret db cr,lf,tab,'Type "EXIT" to return to TinyTerm.',cr,lf,stop
cmdret2 db cr,lf,tab,'Back in TinyTerm.',cr,lf,stop
cmd db cmdlen
cmd1 db ' /C dsz '
cmdr db 'r'
cmdz db 'z '
cmdlen equ $-cmd1
cmdf db 80 dup(0)
cmdmdz db cr,lf,tab,'Attempting Zmodem download using DSZ:'
db cr,lf,lf,stop
cmdmfr db cr,lf,tab,'Attempting Xmodem/CRC download using DSZ.',cr,lf,lf
db cr,lf,tab,'Enter the filename to receive (up to 80 characte'
db 'rs)',cr,lf,'> ',stop
cmdmfs db cr,lf,tab,'Attempting '
XorZ db 'Zmodem upload using DSZ.',cr,lf,lf
db cr,lf,tab,'Enter the path\filename to send (up to 80 charac'
db 'ters)',cr,lf,'> ',stop
edmsg db cr,lf,,tab,'Calling editor.',cr,lf,stop
noedit db cr,lf,tab,bell,'No editor. Use TTSETUP.COM to define one.'
db cr,lf,stop
param dw 0
param1 dw offset cmd
parseg dw ?
dd -1
dd -1
sseg dw ?
sptr dw ?
spec db 'COMSPEC=',0
atdt db 'ATDT'
atdtlen equ $-atdt
at db 'AT',cr
atlen equ $-at
atshort equ atlen - 1
bspeed db cr,lf,lf,tab,'Baud rate set to $'
b300 db '3$'
b1200 db '12$'
b2400 db '24'
bspeed2 db '00 bps.',cr,lf,lf,'$'
epar db cr,lf,lf,tab,'Set to 7 bits, EQUAL'
par2 db ' parity, 1 stop bit.',cr,lf,lf,stop
npar db cr,lf,lf,tab,'Set to 8 bits, NO$'
noblink db '$'
attrib db ''
intense db '0;4'
back db '0;3'
fore db '0m$'
blink db '
$'
cleol db '$'
cls db 'H
$'
up db 'A$'
down db 'B$'
left db 'D$'
right db 'C$'
bracket db '$'
even
avatbl dw offset blink
dw offset up
dw offset down
dw offset left
dw offset right
dw offset cleol
color db black,red,green,brown,blue,magenta,cyan,white
avaflag db 0
rchar db ?
begin: mov bx,(4 * 1024) ; 16 kiloblocks = 1 segment
mov ah,4ah
dos ; release unneeded memory
mov si,offset spec ; find comspec
mov es,es:[2ch] ; environment block
xor di,di ; start from the beginning
spec1: mov bx,si ; pointer to variable
cmp byte ptr es:[di],0 ; not found?
je main1 ; comspec not found, cannot shell
spec2: mov al,[bx] ; read char in variable
or al,al ; is it a final 0?
je spec4 ; yes, comspec found
cmp al,es:[di] ; matching character?
jne spec3 ; nope, try next variable
inc bx ; yes, try next character
inc di ; in both strings
jmp spec2
spec3: xor al,al ; find closing '\0' of nonmatching string
mov cx,0ffffh ; allow for "infinite" length
cld ; check in forward direction
repnz scasb ; until a 0 is matched
jmp spec1 ; try next variable
spec4: mov si,offset command ; copy env variable to data segment
spec5: mov al,es:[di] ; get character
mov [si],al ; and copy it
inc si ; next char
inc di ; in both strings
or al,al ; closing 0?
jne spec5 ; no, copy more
main1: mov ax,ds
mov es,ax
mov parseg,ax
print copr ; say hi
open ; open the channel of communications
setB 1200 ; 1200 baud, 8N1
dtr on ; turn dtr on
chat ; communicate till ^end is hit . . .
ret ; unnecessary, but just in case...
main endp
funkey proc
cmp ah,'^' ; ^ <F1>
jb fkey0 ; not a ^FKEY or ALT-FKEY
cmp ah,'q' ; ALT <F10>
ja fkey0 ; not a ^FKEY or ALT-FKEY
sub ah,'^' ; offset in the table
xchg ah,al ; al = ah, ah = 0
mov bx,ax ;turn into pointer
mov al,macount[bx] ; string length
mov cl,5 ; 32 = 2 ** 5
shl bx,cl ; multiply by 32
add bx,offset macword
mov di,bx
mov cx,ax ; ah still = 0
sends ; send it out to the modem
ret ; return to caller
fkey0: cmp ah,'H' ; <up>
jne f00
mov al,'A'
jmp ansi
f00: cmp ah,'P' ; <down>
jne f01
mov al,'B'
jmp ansi
f01: cmp ah,'M' ; <right>
jne f02
mov al,'C'
jmp ansi
f02: cmp ah,'K' ; <left>
jne f03
mov al,'D'
jmp ansi
f03: cmp ah,'G' ; <home> sweet <home>
jne f04
mov al,'H'
jmp ansi
f04: cmp ah,'O' ; <end>
jne f05
mov al,'K'
jmp ansi
f05: cmp ah,'u' ; ^<end>
je f050 ; finish
cmp ah,'-' ; <alt> <X>
jne f06
f050: exit 0 ; end program
f06: cmp ah,';' ; <F1> send ATDT to the modem
jne f07
sends atdt,atdtlen
ret
f07: cmp ah,'<' ; <F2> send AT<cr>
jne f08
sends at,atlen
ret
f08: cmp ah,'D' ; <F10> help
jne f0a
f09: print help
ret
f0a: cmp ah,'4' ; <F12> of enhanced keyboard - help
je f09
cmp ah,'=' ; <F3> AT, no <cr>
jne f0b
sends at,atshort
ret
f0b: cmp ah,'>' ; <F4>, set 300 baud
jne f0c
mov al,baud
and al,bmask ;remove old baud rate
or al,b3 ; set to 300 bps
mov baud,al
setB
print bspeed
print b300
print bspeed2
ret
f0c: cmp ah,'?' ; <F5> set 1200 baud
jne f0d
mov al,baud
and al,bmask
or al,b12
mov baud,al
setB
print bspeed
print b1200
print bspeed2
ret
f0d: cmp ah,'@' ; <F6>, set 2400 baud
jne f0e
mov al,baud
and al,bmask
or al,b24
mov baud,al
setB
print bspeed
print b2400
ret
f0e: cmp ah,'A' ; <F7>, set 7E1
jne f0f
mov al,baud
and al,pmask
or al,p7E1
mov baud,al
setB
print epar
ret
f0f: cmp ah,'B' ; <F8>, set 8N1
jne f10
mov al,baud
and al,pmask
or al,p8N1
mov baud,al
setB
print npar
print par2
ret
f10: cmp ah,'C' ; <F9>, A/
jne f11
sendc 'A'
sendc '/'
ret
f11: cmp ah,'#' ; <alt> <H>, drop dtr
jne f12
dtr off
print drop
ret
f12: cmp ah,'Q' ; <Page Down>, call zmodem download
jne f14
mov cmdr,'r' ; receive
mov cmd,cmdlen
mov cmdz,'z' ; use Zmodem
mov cmdf,0 ; don't prompt for a file name
mov param1,offset cmd
lea dx,cmdmdz ; Zmodem download message
call exec
jnc f13
print zbad
f13: ret
f14: cmp ah,'' ; <alt> <R>, raise DTR
jne f15
dtr on
print raise
ret
f15: cmp ah,'' ; <alt> <E>, run editor
jne f17
cmp editor,0 ; is an editor defined?
jne f16 ; yes, try to run it
print noedit
ret
f16: mov param1,offset editor
lea dx,edmsg
mov cmdf,0 ; don't prompt for a file name
call exec
ret
f17: cmp ah,'v' ; <ctl> <Page Down>, Xmodem download via DSZ
jnz f18
mov cmdf,1 ; prompt for the filename
mov param1,offset cmd
mov cmdr,'r' ; receive file
mov cmdz,'c' ; using Xmodem/CRC
lea dx,cmdmfr
call exec
ret
f18: cmp ah,'I' ; <Page Up>, Zmodem upload
jnz f19
mov cmdf,1 ; prompt for the file name
mov XorZ,'Z'
mov param1,offset cmd
mov cmdr,'s' ; send
mov cmdz,'z' ; Zmodem
lea dx,cmdmfs
call exec
ret
f19: cmp ah,'ä' ; <ctl> <Page Up>, Xmodem upload
jnz f1a
mov cmdf,1 ; prompt for the file name
mov param1,offset cmd
mov cmdr,'s' ; send
mov cmdz,'x' ; Xmodem
mov XorZ,'X'
lea dx,cmdmfs
call exec
ret
f1a: cmp ah,' ' ; <alt> <D>, drop to DOS
jnz f1b
mov cmdf,0 ; don't prompt for file name
mov param1,offset cmd
mov cmd,0 ; no parameters passed
lea dx,cmdret
call exec
print cmdret2
ret
f1b: ret
ansi: push ax ; save code
sends blink,2 ; <esc>[
pop ax ; restore code
csend ;send it to the modem
ret ; return to caller
funkey endp
avatar proc near
; Enter the procedure with a control character received from the modem
; in AL. Check if it is an advanced video attribute. If so, translate it
; to ANSI and send to the screen. Else, print it unchanged to the screen.
cmp avaflag,0 ;have we started yet?
jne ava1
cmp al,ctlL ;clear screen?
jne a00 ;no, something else
print cls ;thoroughly clean screen
ret ;return to caller
a00: cmp al,ctlY ;repeat character?
jne a02 ;no, try other codes
mov avaflag,yflag ;set flag
ret
a02: cmp al,ctlV ;video code?
je a03 ;yes, parse it
cput ;no, send ctrl code to screen
ret ;and return to caller
a03: mov avaflag,vflag ;set flag
ret
ava1: cmp avaflag,vflag ;are we in ^v ?
jne ava2 ;nope, check further
cmp al,ctlA ;color attribute?
jne ava3 ;no, check further
mov avaflag,aflag ;set flag
ret
ava2: cmp avaflag,yflag ;repeat character?
jne ava4 ;no, check further
mov rchar,al ;save repeat char
mov avaflag,yflag2 ;set flag
ret
ava3: cmp al,ctlG ;something simple?
ja ava5 ;no, need further processing
xor ah,ah ;clean high byte
dec al
dec al ;start at the bottom of table
shl ax,1
mov bx,ax ;convert to pointer
mov dx,avatbl[bx] ;find proper ansi sequence
print ;and send it to the screen
mov avaflag,noflag ;reset the flag
ret ;return to caller
ava4: cmp avaflag,aflag ;are we to set the attribute?
jne ava6 ;nope, check further
mov avaflag,noflag ;reset the flag
test al,imask;intensity bit on?
je a04 ;no
push ax ;print would destroy it
print noblink ;just in case blink is on, turn it off
pop ax ;restore register
mov intense,'1' ;yes, send <esc>[1m
jmp short a05
a04: mov intense,'0' ;send <esc>[0m
a05: push ax ;save for further processing
and al,bkgmask ;find background color
mov cl,4
shr al,cl ;convert to a decimal digit
xor ah,ah ;clean up high byte
mov bx,ax ;convert to a pointer
mov al,color[bx] ;find ANSI color
add al,'0' ;convert to ASCII
mov back,al ;send to escape sequence
pop ax ;restore attribute
and al,fgrmask ;get foreground attribute
xor ah,ah ;clean up high byte
mov bx,ax ;change into pointer
mov al,color[bx] ;find the color
add al,'0' ;convert to ASCII
mov fore,al ;set to escape sequence
print attrib ;send it all to the screen
ret ;return to caller
ava5: cmp al,ctlH ;cursor control?
je ava7 ;yes, process it
push ax ;no, print codes
mov al,ctlV ;first print ^v
cput
pop ax ;restore second character
cput ;and print it
mov avaflag,noflag ;reset the flag
ret ;return to caller
ava6: cmp avaflag,yflag2 ;is it repeat character?
jne ava8 ;no, check further
xor ah,ah ;use just AL
mov cx,ax ;initialize the counter
mov al,rchar ;restore character to print
a01: cput ;print it
loop a01 ;until cx = 0
mov avaflag,noflag ;reset the flag
ret ;return to caller
ava7: mov avaflag,hflag ;set flag
ret
ava8: cmp avaflag,hflag ;cursor control?
jne ava9 ;check further
mov avaflag,hflag2
mov rchar,al ;save row
ret ;return to caller
ava9: cmp avaflag,hflag2 ;column?
jne ava10 ;nope
mov avaflag,noflag ;reset counter
push ax ;save column
print bracket ;print ANSI intro
mov al,rchar ;restore row number
call printno ;and print them
mov al,';' ;separator
cput ;print it out
pop ax ;restore columns
call printno ;print the number
mov al,'f' ;finish the ansi command
cput
ret
ava10: ;theoretically we should never get here....
mov avaflag,noflag ;reset flag
ret
avatar endp
printno proc near
aam ;convert to decimal
or ah,ah ; > 10 ?
jz p00 ;no, do not print tens
push ax ;save units
mov al,ah ;ready to print tens
add al,'0' ;convert to ASCII
cput ;send to screen
pop ax ;restore units
p00: add al,'0' ;convert to ASCII
cput ;send to screen
ret ;return to caller
printno endp
exec proc near
cmp command,0
jne exec1
print nocom
ret
exec1:
print
cmp cmdf,0 ; do we wait for a file name?
je exec2 ; no, skip it
mov ah,3fh
xor bx,bx ; stdin
mov cx,80 ; maximum string length
lea dx,cmdf
dos
add ax,(cmdlen-2) ; count total command tail length w/o cr/lf
mov cmd,al ; and post it
exec2: push ds
push es
mov sseg,ss
mov sptr,sp
mov dx,offset command
mov bx,offset param
mov ax,4b00h
dos
mov ss,sseg
mov sp,sptr
pop es
pop ds
ret
exec endp
dumb ends
end start