home *** CD-ROM | disk | FTP | other *** search
- PAGE 63,132 ;(63 lines long, 132 columns wide)
- TITLE Mark Stout COMASM 5/10/89
- .SALL
- ;==============================================================================
- ;
- ; Mark Stout COMASM.EXE 5/10/89
- ;
- ; COMASM is an integrated terminal emulation package combining two modes,
- ; VT52 and CHAT. While in the VT52 emulation mode, COMASM will impersonate
- ; a DEC VT52, transmitting, receiving and interpreting all escape
- ; sequences in this terminal's command set. While in the CHAT mode, COMASM
- ; allows messages to be sent between two PCs. Any characters
- ; may be sent, in messages up to 256 characters long.
- ;
- ; Data is transmitted and received through the PC's primary serial port,
- ; COM1. COMASM relies on interupts from the UART as opposed to polling
- ; its registers.
- ;
- ;==============================================================================
-
- ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^MACROS^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- ;==============================================================================
- ;
- ; DISPLAY Macro:
- ;
- ; Displays string of characters on standard output. String must be
- ; terminated by '$'.
- ;
- ; Format:
- ;
- ; DISPLAY message
- ;
- ; where message is the offset of the string.
- ;
- ;==============================================================================
-
- DISPLAY MACRO MESSAGE
-
- PUSH DX
- PUSH AX
-
- LEA DX, MESSAGE ;Point to offset of string
- MOV AH, 9H ;Use DOS function 9H
- INT 21H
-
- POP AX
- POP DX
-
- ENDM
-
- ;==============================================================================
- ;
- ; BIN2ASCII Macro:
- ;
- ; Converts binary value in DX to ASCII string.
- ;
- ; Format:
- ;
- ; BIN2ASCII length, out_buffer
- ;
- ; where length is the # of characters for the output string, including
- ; leading spaces, and out_buffer is location of output buffer.
- ;
- ;==============================================================================
-
- BIN2ASCII MACRO LENGTH, OUT_BUFFER
- LOCAL ASCIILOOP, BLANK, NEXT, PAD ;Define local labels for multiple invocations
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
-
- MOV CX, LENGTH ;Set up CX as counter of ASCII digits
- MOV AX, DX ;Move binary value to accumulator
- MOV BX, 10 ;Set up BX as decimal base
-
- ASCIILOOP:
- MOV DI, CX ;Use DI for index relative addressing of ASCII string
- CMP AX, 0 ;If accumulator = 0, pad left of string with blanks
- JE BLANK
- MOV DX, 0 ;Prepare DX as high word of dividend
- DIV BX ;Divide remaining value by decimal base
- ADD DX, 30H ;Convert remainder to ASCII for use in string
- MOV [OUT_BUFFER+DI-1], DL ;Converted remainder is next least significant digit in string
- JMP NEXT
-
- BLANK: CMP CX, LENGTH ;Checks for binary value = 0
- JNE PAD
- MOV [OUT_BUFFER+DI-1], '0'
- JMP NEXT
-
- PAD: MOV [OUT_BUFFER+DI-1], ' ' ;Pads left of string with blanks when necessary
- NEXT: LOOP ASCIILOOP ;Calculate next digit of string
-
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
-
- ENDM
-
- ;===============================================================================
- ;
- ; SCROLL_UP Macro:
- ;
- ; Uses BIOS function INT 10h, Subfunction 6, to scroll a pre-defined
- ; window a given number of lines. New lines are white foreground on
- ; black background.
- ;
- ; Format:
- ;
- ; SCROLL_UP lines, TL_row, TL_col, BR_row, BR_col
- ;
- ; where: lines = # of lines to scroll (0 for entire window)
- ; TL_row = row of top, left corner
- ; TL_col = column of top, left corner
- ; BR_row = row of bottom, right corner
- ; BR_col = column of bottom, right corner
- ;
- ;===============================================================================
-
- SCROLL_UP MACRO LINES, TL_ROW, TL_COL, BR_ROW, BR_COL
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV AH, 6 ;Choose subfunction 6
- MOV AL, LINES ;Initialize registers
- MOV CH, TL_ROW
- MOV CL, TL_COL
- MOV DH, BR_ROW
- MOV DL, BR_COL
- MOV BH, 7
-
- INT 10H
-
- POP DX
- POP CX
- POP BX
- POP AX
-
- ENDM
-
- ;===============================================================================
- ;
- ; SCROLL_DOWN Macro:
- ;
- ; Uses BIOS function INT 10h, Subfunction 6, to scroll a pre-defined
- ; window down a given number of lines. New lines are white foreground on
- ; black background.
- ;
- ; Format:
- ;
- ; SCROLL_DOWN lines, TL_row, TL_col, BR_row, BR_col
- ;
- ; where: lines = # of lines to scroll (0 for entire window)
- ; TL_row = row of top, left corner
- ; TL_col = column of top, left corner
- ; BR_row = row of bottom, right corner
- ; BR_col = column of bottom, right corner
- ;
- ;===============================================================================
-
- SCROLL_DOWN MACRO LINES, TL_ROW, TL_COL, BR_ROW, BR_COL
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV AH, 7 ;Choose subfunction 7
- MOV AL, LINES ;Initialize registers
- MOV CH, TL_ROW
- MOV CL, TL_COL
- MOV DH, BR_ROW
- MOV DL, BR_COL
- MOV BH, 7
-
- INT 10H
-
- POP DX
- POP CX
- POP BX
- POP AX
-
- ENDM
-
- ;===============================================================================
- ;
- ; LOCATE Macro:
- ;
- ; Uses BIOS function INT 10h, Subfunction 2, to position cursor.
- ;
- ; Input: DH = Row coordinate (0-24)
- ; DL = Column coordinate (0-79)
- ;
- ;===============================================================================
-
- LOCATE MACRO
-
- PUSH AX
- PUSH BX
-
- MOV AH, 2 ;Choose subfunction 2
- MOV BH, 0 ;Choose video page
- INT 10H
-
- POP BX
- POP AX
-
- ENDM
-
- ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
- STKSEG SEGMENT STACK ;Stack segment
- DB 512 DUP(?) ;(512 bytes ought to do)
- STKSEG ENDS
-
- CSEG SEGMENT ;Code segment
- ASSUME CS:CSEG, DS:CSEG, SS:STKSEG, ES:NOTHING
-
- ;==============================================================================
- ;
- ; MP3 Main Procedure:
- ;
- ; Sets up data, and calls subroutines. Also performs requested
- ; mode switching and exits.
- ;
- ;==============================================================================
-
- MAIN PROC FAR
- MOV AX, CSEG ;Initialize DS register
- MOV DS, AX
- JMP OLA ;Jump around data
-
- ; Define equates, messages and buffers
-
- MSGCAP EQU 256
- CR EQU 0DH
- LF EQU 0AH
- EOM EQU 0DH
- ESCAPE EQU 27
- XON EQU 17
- XOFF EQU 19
-
- TOP_BORDER DB "╔═════════════════ OUT ════════════════╗╔═════════════════ IN ═════════════════╗$"
- BOT_BORDER DB "╚══════════════════════════════════════╝╚══════════════════════════════════════╝$"
- VERT_BORDER DB "║$"
- INTRO DB "CHAT MODE: Type anything. ENTER sends each message. Hit ESC to exit.$"
- FULL_QUEUE DB "Warning: The transmission queue is full. Please hit ENTER to end the message.$"
- INVALID_MSG DB "Warning: Invalid key was depressed.$"
- TX_POSITION DW ?
- RX_POSITION DW ?
- VT_POSITION DW 0
- LMSG DW 0
- VECTOR_SEG DW ?
- VECTOR_OFF DW ?
- MODE DB ? ;Mode = 3 for VT52 emulation, 1 for CHAT
- STATUS DB "STATUS: Baud: 1200 Parity: N Data Bits: 8 Stop Bit(s): 1$"
- APPLICATION DB 0 ;Indicates numeric keypad application mode.
- ESC_SEQ DB 0
- DCADDRESS_LINE DB ?
- COMM_PAR DB 10000011B ;Communications parameters
- BAUD_PROMPT DB "Select Baud: A)110 B)150 C)300 D)600 E)1200 F)2400 G)4800 H)9600 $"
- PARITY_PROMPT DB "Select Parity: N)one E)ven O)dd $"
- DATA_PROMPT DB "Select Data Bits: 7)Seven 8)Eight $"
- STOP_PROMPT DB "Select Stop Bits: 1)One 2)Two $"
- XOFF_MSG DB "Receiced XOFF. Please stop typing.$"
- FLOW DB 0
-
- ; Call subroutines.
-
- OLA: CALL ISR_INIT ;Install new interupt service routine 0Ch
-
- VT52:
- MOV MODE, 3 ;Update mode indicator
- CALL PORT_INIT
- CALL VT52_SCREEN
- CALL CLEAR_QUEUES
-
- EMU: CALL VT52_INPUT
- CMP AL, 0 ;Could character be for program control?
- JNE NO_ALT
- CMP AH, 24 ;CHAT for Alt-O
- JE CHAT
- CMP AH, 45 ;Exit to DOS for Alt-X
- JE CIAO
-
- NO_ALT: CALL VT52_DISPLAY
- CALL FLOW_CONTROL ;Handle receipt of XOFF.
-
- JMP EMU
-
- CHAT:
- MOV MODE, 1 ;Update mode indicator
- CALL PORT_INIT
- CALL CHAT_SCREEN
- CALL CLEAR_QUEUES
-
- GAB: CALL CHAT_INPUT ;Process characters in keyboard buffer
- CMP AL, ESCAPE ;If escape entered, exit
- JE VT52
-
- CALL RX_DISPLAY ;Display any received character
-
- JMP GAB ;Repeat for next character
-
- CIAO:
- SCROLL_UP 0, 0, 0, 24, 79 ;Blank screen upon exit
-
- MOV DX, VECTOR_OFF
- MOV DS, VECTOR_SEG
- MOV AX, 250CH ;Install original interrupt vector
- INT 21H
-
- MOV AH,4Ch ;DOS code to exit
- INT 21h ;(exit)
-
- MAIN ENDP
-
- ;===============================================================================
- ;
- ; ISR_INIT Subroutine:
- ;
- ; Installs new INT 0Ch vector. Saves original vector for restoration.
- ;
- ;===============================================================================
-
- ISR_INIT PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH DX
- PUSH ES
-
- MOV AX, 350CH ;Get original INT 0Ch vector
- INT 21H
- MOV VECTOR_SEG, ES
- MOV VECTOR_OFF, BX
-
- LEA DX, ISR0C ;Find address of new interupt service routine
- MOV AX, 250CH ;Install vector for new ISR
- INT 21H
-
- POP ES
- POP DX
- POP BX
- POP AX
-
- RET
-
- ISR_INIT ENDP
-
- ;===============================================================================
- ;
- ; ISR0C Interupt Handler:
- ;
- ; Alerted by interupt type 0Ch. Checks for type of UART interupt, and
- ; acts accordingly. If RDA is true, reads character from UART. If THRE
- ; is true, transmits character from TX queue.
- ;
- ;===============================================================================
-
- ISR0C PROC
-
- PUSH AX
- PUSH DX
- PUSH DI
- PUSH DS
-
- MOV AX, CSEG ;Restore data segment register
- MOV DS, AX
-
- MOV DX, 03FAH ;Check Interupt
- IN AL, DX ;Identification Register
- TEST AL, 10B ;Was it a THRE irpt?
- JNZ THRE
-
- MOV DX, 3F8H ;Receive character
- IN AL, DX
-
- CMP AL, XOFF ;Check for XOFF
- JNE ISR1
- MOV FLOW, 0FFH ;Set data flow indicator
- JMP ISR_DONE
-
- ISR1: CMP AL, XON ;Check for XON
- JNE ISR2
- MOV FLOW, 0 ;Reset data flow indicator
- JMP ISR_DONE
-
- ISR2: LEA DI, RQ
- CALL ENQUEUE ;Enqueue received character
- JMP ISR_DONE
-
- THRE:
- LEA DI, TQ ;Dequeue character for transmission
- CALL DEQUEUE
- MOV DX, 03F8H ;Transmit character
- OUT DX, AL
-
- CMP MODE, 1 ;Disable THRE according to mode
- JE CHATTER
- CMP TQ.COUNT, 0 ;Any characters to be sent?
- JNE ISR_DONE
- MOV AL, 01B ;If not, disable THRE irpts
- MOV DX, 03F9H
- OUT DX, AL
- JMP ISR_DONE
-
- CHATTER:
- CMP TQ.NMSGS, 0 ;Any more pending messages to be sent?
- JNE ISR_DONE
- MOV AL, 01B ;If no more messages pending,
- MOV DX, 03F9H ;disable THRE irpts
- OUT DX, AL
-
- ISR_DONE:
- MOV AL, 20H ;Inform UART that ISR is finished
- OUT 20H, AL
-
-
- POP DS
- POP DI
- POP DX
- POP AX
- IRET
-
- ISR0C ENDP
-
- ;===============================================================================
- ;
- ; PORT_INIT Subroutine:
- ;
- ; Initializes primary serial port for the parameters determined by AL.
- ;
- ; Uses BIOS function INT 14h, Subfunction 0.
- ;
- ; Input: COMM_PAR has initialization bit pattern: BBBPPSLL
- ;
- ; Output: COM1 is initialized
- ; ALL REGISTERS PRESERVED
- ;
- ;===============================================================================
-
- PORT_INIT PROC NEAR
-
- PUSH AX
- PUSH DX
-
- MOV DX, 0 ;Choose primary port
- MOV AH, 0 ;Indicate subfunction
- MOV AL, COMM_PAR ;Get communication parameters
- INT 14H ;Initialize port
-
- MOV DX, 3FDH ;Clear out any initial garbage
- IN AL, DX ;in UART register
- TEST AL, 1B
- JE PORT_CLEAR
-
- MOV DX, 3F8H ;Receive garbage character
- IN AL, DX
-
- PORT_CLEAR:
- MOV AL, 01B
- MOV DX, 03F9H
- OUT DX, AL ;Enable RDA irpts
-
- MOV AL, 1011B ;Set OUT2 of the Modem Control Register
- MOV DX, 03FCH ;so UART passes Irpts to the 8259
- OUT DX, AL ;Also, initiate handshaking through DTR and RTS
-
- SHAKE: MOV DX, 03FEH ;Check that modem has completed handshake
- IN AL, DX
- AND AL, 00110000B ;Is modem ready to communicate?
- JZ SHAKE ;If not, wait
-
- IN AL, 21H ;Enable IRQ4 interrupts at
- AND AL, 11101111B ;the 8259 PIC
- OUT 21H, AL
-
- POP DX
- POP AX
-
- RET
-
- PORT_INIT ENDP
-
- ;===============================================================================
- ;
- ; VT52_SCREEN Subroutine:
- ;
- ; Displays status line and positions cursor for VT52 emulation.
- ;
- ;===============================================================================
-
- VT52_SCREEN PROC NEAR
-
- PUSH DX
-
- SCROLL_UP 0, 0, 0, 24, 79
- MOV DX, 1800H
- LOCATE
- DISPLAY STATUS
- MOV DX, VT_POSITION
- LOCATE
-
- POP DX
- RET
-
- VT52_SCREEN ENDP
-
- ;===============================================================================
- ;
- ; VT52_INPUT Subroutine:
- ;
- ; Uses BIOS function INT 16h to check for and retrieve characters typed
- ; on transmitting keyboard. Queues them into TQ.
- ;
- ;===============================================================================
-
- VT52_INPUT PROC NEAR
-
- PUSH BX
- PUSH DI
-
- MOV AH, 1
- INT 16H
- JZ VTI_RESET
-
- MOV AH, 0 ;Accept character from keyboard
- INT 16H
-
- CMP AL, 0 ;Convert special keys, and flag invalid keys
- JNE VT_IN1
- CALL VT52_SPECIAL
- CMP AL, 0 ;Don't enqueue invalid characters
- JE DONE_IN2
-
- VT_IN1: CMP APPLICATION, 0 ;Is keypad in application mode?
- JE VT_IN2
- MOV BL, AL ;If so, add 40 to ASCII value of
- MOV BH, 0 ;keypad characters as part of
- ADD AL, APP_CODES[BX] ;VT52 specs
- PUSH AX
- MOV AL, ESCAPE ;Send ESC ? before application
- LEA DI, TQ ;keypad value
- CALL ENQUEUE
- MOV AL, "?"
- CALL ENQUEUE
- POP AX
-
- VT_IN2: LEA DI, TQ ;Enqueue character for transmission
- CALL ENQUEUE
- PUSH AX
- MOV AL, 11B ;Enable THRE irpts, as character(s)
- MOV DX, 03F9H ;wait for transmission
- OUT DX, AL
- POP AX
- JMP DONE_IN2
-
- VTI_RESET:
- MOV AX, 0 ;If no key entered reset "new key value"
-
- DONE_IN2:
- POP DI
- POP BX
- RET
-
- VT52_INPUT ENDP
-
- APP_CODES DB 12 DUP(0), 40H, 30 DUP(0), 3 DUP(40H), 0, 10 DUP(40H), 200 DUP(0)
-
- ;===============================================================================
- ;
- ; VT52_SPECIAL Subroutine:
- ;
- ; Interprets cursor movement and screen control keys.
- ; Transmits appropriate escape sequence.
- ;
- ;===============================================================================
-
- VT52_SPECIAL PROC NEAR
-
- PUSH BX
- PUSH DX
- PUSH DI
-
- CMP AH, 25 ;Change comm. parameters?
- JNE SPEC1
- CALL LINE_SETTINGS
- JMP FINI
-
- SPEC1: CMP AH, 59 ;Don't interpret invalid key press
- JB FINI
- CMP AH, 118
- JA FINI
-
- MOV BL, AH ;Use look-up table of appropriate sequences
- MOV BH, 0
- SUB BX, 50
- MOV DL, SPECIAL_CODES[BX]
- CMP DL, " " ;Don't interpret invalid keys
- JE FINI
-
- MOV AL, DL ;Get ready for enqueuing sequences
- PUSH AX
- LEA DI, TQ
-
- CMP AL, "J" ;Was it CLEAR SCREEN?
- JNE SPEC2
- MOV AL, ESCAPE ;CLEAR SCREEN is a dual escape sequence
- CALL ENQUEUE
- MOV AL, "H"
- CALL ENQUEUE
-
- SPEC2: MOV AL, ESCAPE ;Enqueue esc of sequence
- CALL ENQUEUE
- POP AX
-
- FINI: POP DI
- POP DX
- POP BX
- RET
-
- VT52_SPECIAL ENDP
-
- SPECIAL_CODES DB " PQRS HA D C KB J"
-
- ;===============================================================================
- ;
- ; VT52_DISPLAY Subroutine:
- ;
- ; Interprets and displays received characters.
- ;
- ;===============================================================================
-
- VT52_DISPLAY PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH DX
- PUSH DI
-
- CMP RQ.COUNT, 0 ;Received characters for display?
- JE VTD_DONE
-
- LEA DI, RQ ;Dequeue next available character
- CALL DEQUEUE
-
- CMP ESC_SEQ, 0 ;Part of esc sequence?
- JE VTD1
- CALL VTD_ESCAPE
- JMP VTD_DONE
-
- VTD1: CMP AL, ESCAPE ;Is character start of escape sequence?
- JNE VTD2
- MOV ESC_SEQ, 0FFH ;Store escape sequence status
- JMP VTD_DONE
-
- VTD2: MOV DX, VT_POSITION ;Position cursor
- LOCATE
- MOV AH, 2 ;Display new character
- MOV DL, AL
- INT 21H
-
- MOV AH, 3 ;Determine new cursor location
- MOV BH, 0
- INT 10H
- CMP DH, 24 ;Is cursor on status line?
- JNE VTD3
- SCROLL_UP 1, 0, 0, 23, 79 ;Scroll if necessary
- MOV DH, 23
- LOCATE
-
- VTD3: MOV VT_POSITION, DX ;Store new cursor location
-
- VTD_DONE:
- POP DI
- POP DX
- POP BX
- POP AX
- RET
-
- VT52_DISPLAY ENDP
-
- ;===============================================================================
- ;
- ; VTD_ESCAPE Subroutine:
- ;
- ; Moves cursor and/or manipulate screen according to escape sequence.
- ;
- ;===============================================================================
-
- VTD_ESCAPE PROC NEAR
-
- PUSH AX
- PUSH DX
-
- CMP ESC_SEQ, 0FFH ;Initial character after escape received?
- JE VE1 ;Yes, jump to code for simple sequences
-
- CMP ESC_SEQ, 0FH ;Final character of Direct Cursor Address?
- JE VE2 ;Yes
- SUB AL, 20H ;No, calculate specified line for LOCATE macro
- CMP AL, 23 ;Check to see line is on screen
- JBE VE3
- MOV AL, 23
- VE3: MOV DCADDRESS_LINE, AL ;Store lin specified by DCA
- MOV ESC_SEQ, 0FH
- JMP VE_DONE
-
- VE2: SUB AL, 20H ;Interpret column of DCA
- CMP AL, 79
- JBE VE4
- MOV AL, 79
- VE4: MOV DL, AL
- MOV DH, DCADDRESS_LINE
- JMP VE_LOC ;Locate cursor
-
- VE1: MOV DX, VT_POSITION ;Interpret simple escape sequences
- CMP AL, "A" ;Up arrow?
- JNE VE5
- CMP DH, 0
- JE VE_RESET
- DEC DH
- JMP VE_LOC
-
- VE5: CMP AL, "B" ;Down arrow?
- JNE VE6
- CMP DH, 23
- JE VE_RESET
- INC DH
- JMP VE_LOC
-
- VE6: CMP AL, "C" ;Right arrow?
- JNE VE7
- CMP DL, 79
- JE VE_RESET
- INC DL
- JMP VE_LOC
-
- VE7: CMP AL, "D" ;Left arrow?
- JNE VE8
- CMP DL, 0
- JE VE_RESET
- DEC DL
- JMP VE_LOC
-
- VE8: CMP AL, "H" ;Home cursor?
- JNE VE9
- MOV DX, 0
- JMP VE_LOC
-
- VE9: CMP AL, "I" ;Reverse Line feed?
- JNE VE10
- CMP DH, 0
- JE ROOM
- DEC DH
- JMP VE_LOC
- ROOM: SCROLL_DOWN 1, 0, 0, 23, 79
- JMP VE_LOC
-
- VE_RESET: ;Reset escape sequence indicator
- MOV ESC_SEQ, 0
- JMP VE_DONE
-
- VE10: CMP AL, "J" ;Erase EOS?
- JNE VE11
- CMP DH, 23
- JE VE12
- CALL CLEAR_BLOCK
- VE12: CALL ERASE_EOL
- JMP VE_LOC
-
- VE11: CMP AL, "K" ;Erase EOL?
- JNE VE13
- CALL ERASE_EOL
- JMP VE_LOC
-
- VE13: CMP AL, "Y" ;Direct Cursor Address?
- JNE VE14
- MOV ESC_SEQ, 0F0H
- JMP VE_DONE
-
- VE14: CMP AL, "Z" ;Identify Terminal?
- JNE VE15
- CALL IDENTIFY
- JMP VE_RESET
-
- VE15: CMP AL, "=" ;Enter Application Keypad Mode?
- JNE VE16
- MOV APPLICATION, 0FFH
- JMP VE_RESET
-
- VE16: CMP AL, ">" ;Exit App Keypad Mode?
- JNE VE_RESET
- MOV APPLICATION, 0
- JMP VE_RESET
-
-
- VE_LOC: LOCATE ;Reposition cursor
- MOV VT_POSITION, DX
- JMP VE_RESET
-
- VE_DONE:
- POP DX
- POP AX
- RET
-
- VTD_ESCAPE ENDP
-
- ;===============================================================================
- ;
- ; CLEAR_BLOCK Subroutine:
- ;
- ; Erases screen below cursor as part of ERASE EOS.
- ; Uses INT 10, Sub 6 to scroll block.
- ;
- ;===============================================================================
-
- CLEAR_BLOCK PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV AH, 6 ;Choose subfunction
- MOV AL, 0 ;Load parameters
- MOV BH, 7
- MOV CH, DH
- INC CH
- MOV CL, 0
- MOV DX, 174FH
- INT 10H ;Erase block
-
- POP DX
- POP CX
- POP BX
- POP AX
- RET
-
- CLEAR_BLOCK ENDP
-
- ;===============================================================================
- ;
- ; ERASE_EOL Subroutine:
- ;
- ; Erases screen to end of current line.
- ; Uses INT 10, Sub 6 to scroll line.
- ;
- ;================================================================================
-
- ERASE_EOL PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV AH, 6 ;Choose subfunction
- MOV AL, 0 ;Load parameters
- MOV BH, 7
- MOV CX, DX
- MOV DL, 79
- INT 10H ;Erase block
-
- POP DX
- POP CX
- POP BX
- POP AX
- RET
-
- ERASE_EOL ENDP
-
- ;===============================================================================
- ;
- ; IDENTIFY Subroutine:
- ;
- ; Sends remote computer identifying string unique to VT52: esc / Z
- ;
- ;===============================================================================
-
- IDENTIFY PROC NEAR
-
- PUSH AX
- PUSH DI
-
- LEA DI, TQ
- MOV AL, ESCAPE ;Send esc
- CALL ENQUEUE
-
- MOV AL, "/" ;Send /
- CALL ENQUEUE
-
- MOV AL, "Z" ;Send Z
- CALL ENQUEUE
-
- POP DI
- POP AX
- RET
-
- IDENTIFY ENDP
-
- ;===============================================================================
- ;
- ; LINE_SETTINGS Subroutine:
- ;
- ; Allows user to alter communication parameters. UART is reset,
- ; and status line updated.
- ;
- ;===============================================================================
-
- LINE_SETTINGS PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH DX
-
- MOV DX, 1800H ;Prompt user for BAUD
- LOCATE
- DISPLAY BAUD_PROMPT
- LS1: MOV AH, 8
- INT 21H ;Get response
- CMP AL, 97
- JB CAPS
- SUB AL, 32
- CAPS: SUB AL, 65
- CMP AL, 7
- JA LS1
- MOV BH, 0
- MOV BL, AL
- SHL BL, 1
- MOV DX, BAUD[BX]
- BIN2ASCII 4, STATUS[17] ;Update status line
- SHL AL, 1 ;Update parameters for UART
- SHL AL, 1
- SHL AL, 1
- SHL AL, 1
- SHL AL, 1
- MOV COMM_PAR, AL
-
- MOV DX, 1800H ;Prompt user for PARITY
- LOCATE
- DISPLAY PARITY_PROMPT
- LS2: MOV AH, 8 ;get response
- INT 21H
- CMP AL, 97 ;Interpret choice
- JB CAPS2
- SUB AL, 32
- CAPS2: CMP AL, "E"
- JE LS3
- CMP AL, "O"
- JE LS4
- CMP AL, "N"
- JE LS5
- JMP LS2
- LS3: OR COMM_PAR, 00011000B ;Update UART parameters
- LS4: OR COMM_PAR, 00001000B
- LS5: MOV STATUS[33], AL
-
- MOV DX, 1800H ;Prompt user for data bits
- LOCATE
- DISPLAY DATA_PROMPT
- LS6: MOV AH, 8 ;Get response
- INT 21H
- CMP AL, "8"
- JE LS7
- CMP AL, "7"
- JE LS8
- JMP LS6
- LS7: OR COMM_PAR, 11B
- LS8: OR COMM_PAR, 10B
- MOV STATUS[49], AL
-
- MOV DX, 1800H ;Prompt user for stop bits
- LOCATE
- DISPLAY STOP_PROMPT
- LS9: MOV AH, 8
- INT 21H ;Get response
- CMP AL, "2"
- JE LS10
- CMP AL, "1"
- JE LS11
- JMP LS9
- LS10: OR COMM_PAR, 100B
- LS11: MOV STATUS[67], AL
-
- MOV DX, 1800H ;Display new status
- LOCATE
- DISPLAY STATUS
- MOV DX, VT_POSITION
- LOCATE
-
- CALL PORT_INIT ;Reinitialize UART
-
- POP DX
- POP BX
- POP AX
-
- RET
-
- LINE_SETTINGS ENDP
-
- BAUD DW 110, 150, 300, 600, 1200, 2400, 4800, 9600
-
- ;===============================================================================
- ;
- ; FLOW_CONTROL Subroutine:
- ;
- ; Implementation of XON/XOFF protocol.
- ;
- ; If XOFF received, informs user and waits for receipt of XON
- ; before further transmission.
- ;
- ;===============================================================================
-
- FLOW_CONTROL PROC NEAR
-
- PUSH DX
-
- CMP FLOW, 0 ;XOFF received?
- JE FC_DONE
-
- MOV DX, 1800H
- LOCATE
- DISPLAY XOFF_MSG ;Inform user of receipt
-
- FC1: CMP FLOW, 0FFH ;Wait for XON
- JE FC1
-
- LOCATE ;Refresh status line
- DISPLAY STATUS
-
- FC_DONE: POP DX
- RET
-
- FLOW_CONTROL ENDP
-
- ;===============================================================================
- ;
- ; CHAT_SCREEN Subroutine:
- ;
- ; Displays windows for transmission and reception of characters.
- ;
- ; Uses the DISPLAY macro to display border elements, the LOCATE macro to
- ; position cursor, and the SCROLL_UP macro to clear the screen.
- ;
- ;===============================================================================
-
- CHAT_SCREEN PROC NEAR
-
- PUSH CX
- PUSH DX
-
- SCROLL_UP 0, 0, 0, 24, 79 ;Blank screen initially
-
- MOV DX, 0
- LOCATE ;Position top border
- DISPLAY TOP_BORDER
-
- MOV DH, 23 ;Position bottom border
- LOCATE
- DISPLAY BOT_BORDER
-
- MOV CX, 22 ;Draw vertical borders down 22 rows
-
- ROW: MOV DH, CL
-
- MOV DL, 0
- LOCATE
- DISPLAY VERT_BORDER
-
- MOV DL, 39
- LOCATE
- DISPLAY VERT_BORDER
-
- MOV DL, 40
- LOCATE
- DISPLAY VERT_BORDER
-
- MOV DL, 79
- LOCATE
- DISPLAY VERT_BORDER
-
- LOOP ROW
-
- MOV DX, 1800H ;Greet user
- LOCATE
- DISPLAY INTRO
-
- MOV TX_POSITION, 0101H
- MOV RX_POSITION, 0129H
- MOV DX, 0101H
- LOCATE
-
- POP DX
- POP CX
-
- RET
-
- CHAT_SCREEN ENDP
-
- ;===============================================================================
- ;
- ; CHAT_INPUT Subroutine:
- ;
- ; Uses BIOS function INT 16h to check for and retrieve characters typed
- ; on transmitting keyboard.
- ;
- ; Output: AL = character typed, or 0 for invalid character
- ; AH DESTROYED
- ;
- ;===============================================================================
-
- CHAT_INPUT PROC NEAR
-
- PUSH DX
- PUSH DI
-
- MOV AH, 1
- INT 16H
- JZ DONE_IN
-
- SCROLL_UP 0, 24, 0, 24, 79 ;Clear status line
-
- MOV AH, 0 ;Accept character from keyboard
- INT 16H
-
- CMP AL, ESCAPE ;Exit for ESC
- JE DONE_IN
-
- CMP AL, 0 ;Convert cursor keys, and flag invalid keys
- JNE CHAR_ENQ
- CALL CURSOR_KEY
- CMP AL, 0 ;Don't enqueue invalid characters
- JE DONE_IN
-
- CHAR_ENQ:
- CMP AL, 9 ;Convert tabs to spaces
- JNE DETABBED
- MOV AL, 32
-
- DETABBED:
- LEA DI, TQ ;Enqueue character for transmission
- CALL ENQUEUE
- JC QUEUE_ERROR ;Alert user of full queue
-
- CMP AL, EOM
- JNE TX_SHOW
- PUSH AX
- MOV AL, 11B
- MOV DX, 03F9H
- OUT DX, AL
- POP AX
-
- TX_SHOW:
- CALL TX_DISPLAY ;Display characters
-
- DONE_IN:
- POP DI
- POP DX
- RET
-
- QUEUE_ERROR: ;Display warning and instruction to user
- MOV DX, 1800H
- LOCATE
- DISPLAY FULL_QUEUE
- JMP DONE_IN
-
- CHAT_INPUT ENDP
-
- ;===============================================================================
- ;
- ; CURSOR_KEY Subroutine:
- ;
- ; Converts cursor-movement-key scan codes into unused ASCII values
- ; for display and transmission. Also alerts user of invalid key
- ; entries. Uses DISPLAY and LOCATE macros to display message.
- ;
- ; Input: AH = scan code to be converted.
- ;
- ; Output: AL = ASCII value
- ;
- ;===============================================================================
-
- CURSOR_KEY PROC NEAR
-
- CMP AH, 72 ;Up arrow?
- JE UP_TX
- CMP AH, 75 ;Left arrow?
- JE LEFT_TX
- CMP AH, 77 ;Right arrow?
- JE RIGHT_TX
- CMP AH, 80 ;Down arrow?
- JE DOWN_TX
-
- MOV AL, 0
- MOV DX, 1800H
- LOCATE
- DISPLAY INVALID_MSG ;All other special keys are invalid
- RET
-
- UP_TX: MOV AL, 30 ;Convert cursor keys to
- RET ;unused ASCII values
-
- LEFT_TX: MOV AL, 29
- RET
-
- RIGHT_TX: MOV AL, 28
- RET
-
- DOWN_TX: MOV AL, 31
- RET
-
- CURSOR_KEY ENDP
-
- ;===============================================================================
- ;
- ; TX_DISPLAY Subroutine:
- ;
- ; Displays characters typed into keyboard for transmission. Uses DOS
- ; function 2, as well as LOCATE and SCROLL_UP macros for display.
- ; BIOS INT 10, subfunction 3 used to determine cursor location.
- ;
- ;===============================================================================
-
- TX_DISPLAY PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
-
- MOV DX, TX_POSITION ;Position cursor properly in OUT window
-
- ;Interpret cursor movement keys
-
- CMP AL, 8 ;Backspace?
- JE TD_LEFT
-
- CMP AL, 29 ;Left arrow?
- JNE TD_NL
- TD_LEFT: CMP DL, 1
- JE TD_STEP
- DEC DL
- LOCATE
- JMP TD_SAVE
-
- TD_NL: CMP AL, 28 ;Right arrow?
- JNE TD_NR
- CMP DL, 38
- JE TD_STEP
- INC DL
- LOCATE
- JMP TD_SAVE
-
- TD_NR: CMP AL, 30 ;Up arrow?
- JNE TD_NU
- CMP DH, 1
- JE TD_STEP
- DEC DH
- LOCATE
- JMP TD_SAVE
-
- TD_STEP: LOCATE ;Used to facilitate long range, conditional jumps
- JMP TD_DONE
-
- TD_NU: CMP AL, 31 ;Down arrow?
- JNE TD_ND
- TD_DOWN: CMP DH, 22
- JE TD_BOTTOM
- INC DH
- LOCATE
- JMP TD_SAVE
- TD_BOTTOM: SCROLL_UP 1, 1, 1, 22, 38 ;Scroll window 1 line if neccessary
- LOCATE
- JMP TD_DONE
-
- TD_ND: CMP AL, CR ;Carriage return?
- JNE TD_NC
- MOV DL, 1
- JMP TD_DOWN
-
- TD_NC: CMP AL, LF ;Line feed? (interpret same as down arrow)
- JE TD_DOWN
- CMP AL, 0BH ;Vertical tab? (same as down arrow)
- JE TD_DOWN
- CMP AL, 0CH ;Form feed? (same as down arrow)
- JE TD_DOWN
-
- ;Display non-movement characters
- CMP DL, 39 ;Character on right edge of window?
- JNE TD_SHOW
- MOV DL, 1 ;Wrap around to next line
- CMP DH, 22
- JNE TD_LINE
- SCROLL_UP 1, 1, 1, 22, 38 ;Scroll 1 line if neccessary
- JMP TD_SHOW
-
- TD_LINE: INC DH ;Move down a line
- TD_SHOW: LOCATE
- MOV AH, 2
- MOV DL, AL
- INT 21H ;Display Character
-
- MOV AH, 3
- MOV BH, 0
- INT 10H ;Determine location of cursor
- TD_SAVE:
- MOV TX_POSITION, DX ;Store current location
-
- TD_DONE:
- POP DX
- POP CX
- POP BX
- POP AX
- RET
-
- TX_DISPLAY ENDP
-
- ;===============================================================================
- ;
- ; RX_DISPLAY Subroutine:
- ;
- ; Displays any messages received from serial port. Uses DOS
- ; function 2, as well as LOCATE and SCROLL_UP macros for display.
- ; BIOS INT 10, subfunction 3 used to determine cursor location.
- ;
- ;===============================================================================
-
- RX_DISPLAY PROC NEAR
-
- PUSH AX
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DI
-
- CMP RQ.NMSGS, 0 ;Pending messages for display?
- JNE DEQUIT
- JMP RD_DONE
-
- DEQUIT: LEA DI, RQ ;Dequeue next available character
- CALL DEQUEUE
-
- MOV DX, RX_POSITION ;Position cursor properly in window
-
- ;Interpret cursor movement keys
-
- CMP AL, 8 ;Backspace?
- JE RD_LEFT
-
- CMP AL, 29 ;Left arrow?
- JNE RD_NL
- RD_LEFT: CMP DL, 41
- JE RD_STEP
- DEC DL
- LOCATE
- JMP RD_SAVE
-
- RD_NL: CMP AL, 28 ;Right arrow?
- JNE RD_NR
- CMP DL, 78
- JE RD_STEP
- INC DL
- LOCATE
- JMP RD_SAVE
-
- RD_NR: CMP AL, 30 ;Up arrow?
- JNE RD_NU
- CMP DH, 1
- JE RD_STEP
- DEC DH
- LOCATE
- JMP RD_SAVE
-
- RD_STEP: LOCATE ;Intermediate step for long range
- JMP RD_DONE ;conditional jump
-
- RD_NU: CMP AL, 31 ;Down arrow?
- JNE RD_ND
- RD_DOWN: CMP DH, 22
- JE RD_BOTTOM
- INC DH
- LOCATE
- JMP RD_SAVE
- RD_BOTTOM: SCROLL_UP 1, 1, 41, 22, 78 ;Scroll 1 line if neccessary
- LOCATE
- JMP RD_DONE
-
- RD_ND: CMP AL, CR ;Carriage return?
- JNE RD_NC
- MOV DL, 41
- JMP RD_DOWN
-
- RD_NC: CMP AL, LF ;Line feed? (Interpret like down arrow)
- JE RD_DOWN
- CMP AL, 0BH ;Vertical tab? (same as down arrow)
- JE RD_DOWN
- CMP AL, 0CH ;Form feed? (same as down arrow)
- JE RD_DOWN
-
- ;Display non-movement characters
- CMP DL, 79 ;Wrap line if neede
- JNE RD_SHOW
- MOV DL, 41
- CMP DH, 22
- JNE RD_LINE
- SCROLL_UP 1, 1, 41, 22, 78 ;Scroll 1 line if needed
- JMP RD_SHOW
-
- RD_LINE: INC DH ;Move down one line for wrap
- RD_SHOW: LOCATE ;Position cursor
- MOV AH, 2
- MOV DL, AL
- INT 21H ;Display character
-
- MOV AH, 3
- MOV BH, 0
- INT 10H ;Determine current location of cursor
- RD_SAVE:
- MOV RX_POSITION, DX ;Store location
-
- RD_DONE:
- POP DI
- POP DX
- POP CX
- POP BX
- POP AX
- RET
-
- RX_DISPLAY ENDP
-
- ;===============================================================================
- ;
- ; ENQUEUE Subroutine:
- ;
- ; Used to enqueue the character in AL into specified queue.
- ;
- ; Input: AL = character to be enqueued
- ; DI = pointer to queue
- ;
- ; Output: CF = 1 if attempted enqueue failed due to full queue
- ; CF = 0 otherwise
- ; [DI].REAR updated
- ; [DI].COUNT incremented if enqueue successful
- ; [DI].NMSGS incremented if character is EOM
- ; THRE interupts enabled if character is EOM
- ;
- ;===============================================================================
-
- ENQUEUE PROC NEAR
-
- PUSH DX
- PUSH SI
-
- CMP DI, OFFSET RQ ;Don't check RQ for full queue
- JE ENQ1
-
- CMP AL, EOM ;Don't check for full queue if EOM
- JNE TQ_NOT_EOM
- MOV LMSG, 0
- JMP ENQ1
-
- TQ_NOT_EOM:
- CMP LMSG, MSGCAP ;Check TQ for full queue
- STC ;Assume full queue
- JNE ENQ0
- JMP DONE_ENQ
-
- ENQ0: INC LMSG ;Increment current msg length for TQ
-
- ENQ1: MOV SI, [DI].REAR ;Adjust the rear pointer
- CMP SI, [DI].QBEG
- JA ENQ2
- ADD SI, QCAPAC
- ENQ2: DEC SI
- MOV [DI].REAR, SI
- MOV [SI], AL ;Enque the character
-
- INC [DI].COUNT ;Update queue count
-
- CMP AL, EOM
- CLC
- JNE DONE_ENQ
- INC [DI].NMSGS ;If EOM, increment pending messages
-
- DONE_ENQ:
- POP SI
- POP DX
- RET
-
- ENQUEUE ENDP
-
- ;===============================================================================
- ;
- ; DEQUEUE Subroutine:
- ;
- ; Used to dequeue a character into AL from specified queue.
- ;
- ; Input: DI = pointer to queue
- ;
- ; Output: AL = character dequeued
- ; [DI].FRONT updated
- ; [DI].COUNT decremented
- ; [DI].NMSGS decremented if character = EOM
- ;
- ;===============================================================================
-
- DEQUEUE PROC NEAR
-
- PUSH DX
- PUSH SI
-
- DEC [DI].COUNT ;Update queue counter
-
- MOV SI, [DI].FRONT ;Adjust the front pointer
- CMP SI, [DI].QBEG
- JA DEQ1
- ADD SI, QCAPAC
- DEQ1: DEC SI
- MOV [DI].FRONT, SI
- MOV AL, [SI] ;Dequeue the character
-
- CMP AL, EOM ;Check for end of message
- JNE DEQ2
- DEC [DI].NMSGS
-
- DEQ2: POP SI
- POP DX
- RET
-
- DEQUEUE ENDP
-
- ;===============================================================================
- ;
- ; CLEAR_QUEUES Subroutine:
- ;
- ; Wipes transmit and receive queues clear for switching modes.
- ;
- ;===============================================================================
-
- CLEAR_QUEUES PROC NEAR
-
- PUSH AX
-
- MOV AX, RQ.QBEG ;Reinitialize receive queue
- ADD AX, QCAPAC
- MOV RQ.FRONT, AX
- MOV RQ.REAR, AX
- MOV RQ.COUNT, 0
- MOV RQ.NMSGS, 0
-
- MOV AX, TQ.QBEG ;Reinitialize transmit queue
- ADD AX, QCAPAC
- MOV TQ.FRONT, AX
- MOV TQ.REAR, AX
- MOV TQ.COUNT, 0
- MOV TQ.NMSGS, 0
-
- POP AX
- RET
-
- CLEAR_QUEUES ENDP
-
- ;===============================================================================
- ;
- ; Queue Structures:
- ;
- ; TQ is used to hold up to 512 characters before transmission.
- ; RQ is used to hold up to 512 characters, after reception, but
- ; before display.
- ;
- ;===============================================================================
-
- QSTRUC STRUC
- FRONT DW ? ;Ptr to last character dequeued
- REAR DW ? ;Ptr to last character enqueued
- QBEG DW ? ;Offset of first byte of queue
- COUNT DW ? ;Number of bytes currently in queue
- NMSGS DW ? ;Number of messages pending
- QSTRUC ENDS
-
- QCAPAC EQU 512
-
- TQBEG DB QCAPAC DUP('T') ;Allocate space for queues
- RQBEG DB QCAPAC DUP('R')
-
- ;Initialize queues
- TQ QSTRUC <TQBEG+QCAPAC, TQBEG+QCAPAC, TQBEG, 0, 0>
- RQ QSTRUC <RQBEG+QCAPAC, RQBEG+QCAPAC, RQBEG, 0, 0>
-
-
- CSEG ENDS
- END MAIN
-