home *** CD-ROM | disk | FTP | other *** search
- name talk
- page 55,132
- .lfcond ;list false conditionals too
- title 'TALK --- IBM PC terminal emulator'
- ;
- ; TALK.ASM --- a simple terminal emulator for the IBM PC
- ;
- ; Copyright (c) 1983, 1984, 1985 Ray Duncan
- ;
- ; To assemble, link, and convert this program into
- ; a COM file, follow these steps:
- ;
- ; C>MASM TALK;
- ; C>LINK TALK;
- ; C>EXE2BIN TALK.EXE TALK.COM
- ; C>DEL TALK.EXE
- ;
- ; Ignore the message "Warning: no stack segment" from the Linker.
-
- cr equ 0dh ;ASCII carriage return
- lf equ 0ah ;ASCII line feed
- bsp equ 08h ;ASCII backspace
- esc equ 1bh ;ASCII escape code
-
- dattr equ 07h ;display attribute to use
- ;while in emulation mode
-
- echo equ 0 ;0=full-duplex, -1=half-duplex
-
- comm_port equ 0 ;set =0 for COM1, <>0 for COM2
-
- pic_mask equ 21h ;port address, 8259 mask register
- pic_eoi equ 20h ;port address, 8259 EOI instr.
-
- if comm_port ;define physical port assignments
- comm_data equ 02f8h ;for COM2
- comm_ier equ 02f9h
- comm_mcr equ 02fch
- comm_stat equ 02fdh
- com_int equ 0bh
- int_mask equ 08h ;Mask for 8529, COM2 is IRQ3
- else
- comm_data equ 03f8h ;port assignments for COM1
- comm_ier equ 03f9h
- comm_mcr equ 03fch
- comm_stat equ 03fdh
- com_int equ 0ch
- int_mask equ 10h ;Mask for 8259, COM1 is IRQ4
- endif
- page
-
- cseg segment para public 'CODE'
-
- org 100h
-
- assume cs:cseg,ds:cseg,es:cseg,ss:cseg ;COM file...
-
- talk proc far ;entry point from PC-DOS
-
- ;initialize display for
- ;terminal emulator mode
-
- mov ah,15 ;determine display width
- int 10h ;using get mode function of ROM
- dec ah ;BIOS video driver, save it for use
- mov columns,ah ;by the screen clear routine.
- cmp al,7 ;make sure display is text mode.
- je talk2 ;mode 7 ok, proceed
- cmp al,3
- jbe talk2 ;modes 0-3 ok,proceed
- mov dx,offset msg1
- jmp talk6 ;print error message and exit
-
- talk2:
- mov bh,dattr ;now clear screen with special
- call cls ;attribute if needed, home cursor
-
- call asc_enb ;set up communications interrupt
- ;service routine and enable int.
-
- talk3: call pc_stat ;check character waiting
- ;from the IBM PC keyboard
- jz talk4 ;nothing waiting, jump
- call pc_in ;read char. from PC keyboard
- cmp al,0 ;is it a function key?
- jne talk32 ;not function key, jump
- call pc_in ;read and discard the 2nd char
- ;of function key sequence
- jmp talk5 ;then exit the terminal emulator
-
- talk32: ;character received from PC keyboard
- if echo
- push ax ;if running half-duplex, echo
- call pc_out ;the character to the PC display
- pop ax
- endif
- call com_out ;write char. to the comm port
-
- talk4: call com_stat ;check if character waiting
- ;from the comm port
- jz talk3 ;no, loop
- call com_in ;read char. from comm port
-
- cmp al,20h ;is it control code?
- jae talk45 ;no
- call ctrl_code ;yes,process it
- jmp talk3 ;check local keyboard
-
- talk45:
- call pc_out ;write it to the PC display
- jmp talk4 ;see if any more waiting
-
- talk5: ;ESC key detected, prepare
- ;to exit the terminal emulator.
- mov bh,07h ;clear screen & home cursor
- call cls ;with "normal" video attribute
- mov dx,offset msg2 ;print farewell message
-
- talk6: push dx ;save message addr
- call asc_dsb ;disable controller and
- pop dx ;release interrupt vector
- mov ah,9 ;print message
- int 21h
- mov ax,4c00h ;exit with ret code=0
- int 21h
-
- talk endp
-
-
- com_stat proc near ;Check asynch status, returns
- ;Z=false if character ready
- ;Z=true if nothing waiting
- push dx
- mov dx,asc_in ;compare ring buffer pointers
- cmp dx,asc_out
- pop dx
- ret
- com_stat endp
-
-
- com_in proc near ;get a char from asynch line
- push bx ;returns char in AL
- com_in1: ;if no char waiting, loop
- mov bx,asc_out ;until one is received.
- cmp bx,asc_in
- je com_in1
- mov al,[bx+asc_buf]
- inc bx
- cmp bx,asc_buf_len
- jne com_in2
- xor bx,bx ;reset ring pointer
- com_in2:
- mov asc_out,bx ;store updated pointer
- pop bx
- ret
- com_in endp
-
-
- com_out proc near ;write character in AL to COM port
- push dx
- push ax ;save char
- mov dx,comm_stat ;check TBE status
- com_out1:
- in al,dx
- and al,20h
- jz com_out1
- pop ax ;write char
- mov dx,comm_data
- out dx,al
- pop dx
- ret
- com_out endp
-
-
- pc_stat proc near ;read status for the IBM
- ;PC's keyboard, returns
- ;Z=false if character ready
- ;Z=true if nothing waiting.
- ;register DX destroyed.
- mov al,in_flag ;if a character is already
- or al,al ;waiting,just return status
- jnz pc_stat1
- mov ah,6 ;otherwise call PC-DOS to
- mov dl,0ffh ;determine status
- int 21h
- jz pc_stat1 ;jump,nothing ready
- ;got a char, save it for
- ;"pc_in" routine.
- mov in_char,al
- mov in_flag,0ffh
- pc_stat1: ;return to caller with
- ret ;Z flag set appropriately
- pc_stat endp
-
-
- pc_in proc near ;read a character from the
- ;IBM PC's keyboard, return
- ;it in AL. DX may be destroyed.
- mov al,in_flag
- or al,al ;any character waiting?
- jnz pc_in1 ;yes,return it to caller
- call pc_stat ;try and read a character
- jmp pc_in
- pc_in1: mov in_flag,0 ;clear char waiting flag
- mov al,in_char ;exit with AL=char
- ret
- pc_in endp
-
-
- pc_out proc near ;write the character in AL
- ;to the PC's display.
- mov ah,0eh ;use ROM BIOS TTY output fxn
- push bx ;save register
- xor bx,bx ;assume page 0
- int 10h ;call ROM BIOS video driver
- pop bx ;restore register
- ret
- pc_out endp
-
-
- cls proc near ;clear the display and set
- ;it to the attribute in BH.
- ;registers AX, CX, DX destroyed.
- mov dl,columns
- mov dh,24 ;DL,DH=X,Y of lower right
- ;corner of "window".
- mov cx,0 ;CL,CH=X,Y of upper left
- ;corner of "window".
- mov ax,600h ;AH=6 for "scroll or initialize
- ;window" function, AL=0 for
- ;number of lines to scroll.
- int 10h ;call ROM BIOS video driver.
- call home ;set cursor at (0,0)
- ret
- cls endp
-
-
- clreol proc near ;clear from cursor to end of line
- ;using the attribute in BH.
- ;registers AX, CX, DX destroyed.
- call getxy
- mov cx,dx ;current position = "upper left"
- ;corner of window
- mov dl,columns ;for "lower right", X is max columns,
- ; Y is the same
- mov ax,600h ;AH=6 for "scroll or initialize
- ;window" function, AL=0 for
- ;number of lines to scroll.
- int 10h ;call ROM BIOS video driver.
- ret
- clreol endp
-
-
- home proc near ;home cursor (set X,Y=0,0)
- mov dx,0
- call gotoxy
- ret
- home endp
-
-
- gotoxy proc near ;position the cursor, call
- ;with (DL,DH)=(X,Y)
- push bx ;save registers
- push ax
- mov bh,0 ;assume page 0
- mov ah,2
- int 10h ;call ROM BIOS video driver
- pop ax ;restore registers
- pop bx
- ret
- gotoxy endp
-
-
- getxy proc near ;get the current cursor position,
- ;returns (DL,DH)=(X,Y)
- push ax ;save registers
- push bx
- push cx
- mov ah,3
- mov bh,0 ;assume page 0
- int 10h ;call ROM BIOS video driver
- pop cx ;restore registers
- pop bx
- pop ax
- ret
- getxy endp
-
-
- ctrl_code proc near ;process a control code character
- ;call with AL=char
- cmp al,cr ;if line feed or carriage
- je ctrl8 ;return, just send it
- cmp al,lf
- je ctrl8
- cmp al,bsp ;or if backspace, just send it
- je ctrl8
-
- cmp al,26 ;is it clearscreen
- jne ctrl7 ;no,jump
- mov bh,dattr
- call cls ;clear screen and home cursor
- ret
-
- ctrl7:
- cmp al,esc ;is it escape char?
- jne ctrl9 ;no,throw it away
- call esc_seq ;yes,emulate CRT terminal
- ret
-
- ctrl8: call pc_out ;send CR or LF to display
-
- ctrl9: ret ;and exit
-
- ctrl_code endp
-
-
- esc_seq proc near ;decode Televideo 950 escape
- ;sequence to control the screen
- call com_in
- cmp al,84 ;clear to end of line
- jne esc_seq1
- mov bh,dattr
- call clreol
- ret
- esc_seq1:
- cmp al,61 ;cursor positioning
- jne esc_seq2
- call com_in ;get Y
- sub al,33 ;remove offset
- mov dh,al
- call com_in ;get X
- sub al,33 ;remove offset
- mov dl,al
- call gotoxy ;set cursor
- esc_seq2:
- ret
- esc_seq endp
-
-
- asc_enb proc near ;set up communications interrupt
- ;vector, and enable interrupt
- mov ah,35h ;get current address of asynch
- mov al,com_int ;port's interrupt handler
- int 21h ;ES:BX = addr
- mov intc_seg,es ;save segment
- mov intc_offs,bx ;save offset
-
- mov dx,offset asc_int
- mov ah,25h ;set address of new handler
- mov al,com_int
- int 21h
-
- mov dx,comm_mcr ;modem controller DTR & OUT2
- mov al,0bh
- out dx,al
-
- mov dx,comm_ier ;interrupt enable register
- mov al,1 ;on asynch controller
- out dx,al
-
- in al,pic_mask ;read current 8259 int. mask
- and al,not int_mask ;reset mask for this COM port
- out pic_mask,al ;write back 8259 int. mask
-
- ret
-
- asc_enb endp
-
- asc_dsb proc near ;disable interrupt and release
- ;service vector
- ;vector, and enable interrupt
-
- in al,pic_mask ;read current 8259 int. mask
- or al,int_mask ;set mask for this COM port
- out pic_mask,al ;write int. mask back to 8259
-
- push ds
- mov dx,intc_offs ;saved offset
- mov ds,intc_seg ;saved segment
- mov ah,25h ;restore address of original
- mov al,com_int ;com port interrupt handler
- int 21h
- pop ds
- ret
- asc_dsb endp
-
-
- asc_int proc far ;interrupt service routine
- ;for asynch controller
-
- sti ;turn interrupts back on
- push ax ;save all necessary registers
- push bx
- push dx
- push ds
- mov ax,cs
- mov ds,ax
- mov dx,comm_data
- in al,dx ;read this character
- cli ;clear interrupts for
- ;pointer manipulation
- mov bx,asc_in ;get buffer pointer
- mov [asc_buf+bx],al ;store this character
- inc bx ;bump pointer
- cmp bx,asc_buf_len ;time for wrap?
- jne asc_int1 ;no,jump
- xor bx,bx ;yes,reset pointer
- asc_int1:
- mov asc_in,bx ;store back updated pointer
- sti ;turn interrupts back on
- mov al,20h ;send EOI to 8259
- out pic_eoi,al
- pop ds ;restore all registers
- pop dx
- pop bx
- pop ax
- iret ;and exit handler
- asc_int endp
-
-
- in_char db 0 ;PC keyboard input char.
- in_flag db 0 ;<>0 if char waiting
-
- columns db 0 ;highest numbered column in
- ;current display mode (39 or 79)
-
- msg1 db cr,lf,'Display must be text mode.'
- db cr,lf,'$'
-
- msg2 db cr,lf,lf,'Exit from terminal emulator.'
- db cr,lf,'$'
-
- intc_offs dw 0 ;original contents of Int 0CH
- intc_seg dw 0 ;service vector
-
- asc_in dw 0 ;input pointer to ring buffer
- asc_out dw 0 ;output pointer to ring buffer
-
- asc_buf_len equ 16384
-
- asc_buf equ this byte
-
- cseg ends
-
- end talk