home *** CD-ROM | disk | FTP | other *** search
- TITLE PCREMOT2 - Unattended Computer Access - 1991 by Terry Lahman
- PAGE 78,132
- ;======================================================================
- ;
- ; PCREMOT2 - An unattended computer access utility. Allows access to an
- ; unattended computer from a manned computer. The unattended computer
- ; executes the TSR portion of the program and waits for the manned
- ; computer to call. For use with text only programs. Like using the
- ; phone lines and modems as a long extension cord for your keyboard
- ; and monitor.
- ;
- ; Usage: PCREMOT2 [ /M ] [ /# ] [ /B# ] [ /D ] [ /S ] [ /N ] [ /U ] [ /? ]
- ;
- ; [ /M ] = "Manned" mode (used on remote system)
- ; [ /# ] = 1 - 4, Communication port used
- ; [ /B# ] = Baud rate 1=1200, 2=2400, 4=4800, 9=9600
- ; 19=19200, 3=38400
- ; [ /D ] = "Desnow" flag (used on CGA monitors)
- ; [ /S ] = Smiley face displayed (used on host system)
- ; [ /N ] = Null modem cable connecting 2 systems
- ; [ /U ] = Uninstall (used on host computer to remove from memory) "
- ; [ /? ] = Display help screen
- ;
- ;======================================================================
- CSEG SEGMENT PARA PUBLIC 'CODE'
- ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
-
- BS EQU 8
- CR EQU 13
- LF EQU 10
- SPACE EQU 32
- ESC_KEY EQU 1BH
-
- ;----------------------------------------------------------------------
- ; Start of code
- ;----------------------------------------------------------------------
- ORG 100H ;Starting offset for .com
- START: JMP INITIALIZE ;Jump over resident code
- DW OFFSET CONFIG - $ ;Offset to config parameters
-
- ;----------------------------------------------------------------------
- ; Data storage
- ;----------------------------------------------------------------------
-
- COPYRIGHT DB "PCREMOT2 Version 1.0 (c) 1989, 1991 Ziff Communications Co."
- DB CR,LF," PC Magazine ",254," by Terry Lahman & Kevin Sims"
- DB CR,LF,"$",26
- CONNECT_FLAG DB 0 ;0=not connected
- ;1=connected to manned system
- ACT_FLAG DB 0 ;0=unattended prog not active
- ;1=unattended program is active
- ; do not run again
- OLDINT_8 DW 0,0 ;Old timer vector
- OLDINT_21 DW 0,0 ;Old DOS vector
- OLDINT_COMM DW 0,0 ;Old communications vector
- INSTALLED_SEG DW 0 ;Segment of resident program
- SET_VEC DW 2500H ;DOS set vector call
- SLEEP_FLAG DB 0 ;0=pcremote is awake
- ;1=pcremote is asleep
- ;needs to sleep during init.
- CURRENT_SPEED DB 0 ;Currently selected speed
- SPEED_COUNT DB 0 ;Change speed once a second
- COMM_PORT DW 0 ;Comm port address
- COMM_INT_STA DB 0 ;Comm port interrupt status
- ;0=not transmitting data
- ;1=transmitting data
- VIDEO_COPY DW 0 ;Address of video ram copy
- VIDEO_SEGMENT DW 0 ;Segment register for vid ram
- SHIFT_STATUS DB 0 ;Current status of shift byte
- STACK_TOP DW INITIALIZE+256D ;Top of stack for unattended
- OLD_SS DW 0 ;Old stack segment
- OLD_SP DW 0 ;Old stack pointer
- TEMP_REG DW 0 ;Temp storage for register
- CURSOR_POSITION DW 0 ;Old cursor position
- VID_RAM_OFFSET DW 0 ;Current compare offset
- ASCII_FLAG DB 0 ;0=no data is pending
- ;1=received a FE
- ;2=received ASCII char
- ;4=received scan code
- SHIFT_FLAG DB 0 ;0=no data is pending
- ;1=received a FD
- KEY_ONE DB 0 ;ASCII char received
- KEY_TWO DB 0 ;Scan code received
- BAUD_RATE DB 0,60H ;1200 BAUD divisor MSB LSB
- DB 0,30H ;2400 BAUD divisor MSB LSB
- DB 0,18H ;4800 BAUD divisor MSB LSB
- DB 0,0CH ;9600 BAUD divisor MSB LSB
- DB 0,06H ;19200 BAUD divisor MSB LSB
- DB 0,03H ;38400 BAUD divisor MSB LSB
- IN_BUFF_SIZE EQU 256D ;Size for input buffer
- OUT_BUFF_SIZE EQU 256D ;Size for output buffer
- IN_BUFF_HEAD DW ? ;Pointer to input buffer head
- IN_BUFF_TAIL DW ? ;Pointer to input buffer tail
- IN_BUFF_BEGIN DW ? ;Pointer to input buffer begin
- IN_BUFF_END DW ? ;Pointer to input buffer end
- OUT_BUFF_HEAD DW ? ;Pointer to output buffer head
- OUT_BUFF_TAIL DW ? ;Pointer to output buffer tail
- OUT_BUFF_BEGIN DW ? ;Pointer to output buffer begin
- OUT_BUFF_END DW ? ;Pointer to output buffer end
- BLOCK_SIZE EQU 16D ;Block transfer size in words
- BLOCK_SIZEX2 EQU BLOCK_SIZE*2 ;Block transfer size in bytes
- BLOCK_COUNT DB ? ;Block number being processed
- BLOCK_POINTER DW 0 ;Points to current video block
- TEMP_VIDEO_PTR DW ? ;Pointer to temp video storage
- CR_COUNT DB ? ;Number of CRs for speed sync
- MODEM_ATTENTION DB CR,"AT",CR,0
- MODEM_SETUP1 DB "ATE0 S12=40 Q0 V0 X1 S0=0",CR,0 ;Manned
- MODEM_SETUP2 DB "ATE0 S12=40 Q1S0=2",CR,0 ;Unattended
- MODEM_SETUP3 DB "AT&C1",CR,0 ;Enable DCD on 2400 baud modem
- MODEM_SETUP4 DB "ATW0X4&Q5&K3L0",CR,0 ;for 9600 baud modems
- MODEM_HANGUP DB "ATH0",CR,0
- MODEM_ESCAPE DB "+++",0
- PASS_MESSAGE DB "Enter password:",0 ;Enter password message
- PASSWORD_BUFFER DB 20 DUP(?)
- BAD_PASSWORD DB ? ;0=No, don't send exit code
- ;1=Yes, 3 bad, so send code
- CONFIG: ;The following parameters must remain in order to support
- ; the setup program.
- MANNED_FLAG DB 0 ;0=Operate in unattended mode
- ;1=Operate in manned mode
- COMM_FLAG DB 0 ;0=Use comm1
- ;1=Use comm2
- ;2=Use comm3
- ;3=Use comm4
- COMM_PORT3 DW 03E8H ;Port address for COMM 3
- COMM_PORT4 DW 02E8H ;Port address for COMM 4
- COMM3_INT DB 4 ;Interrupt for com1 and 3
- COMM4_INT DB 3 ;Interrupt for com2 and 4
- SPEED_FLAG DB 0 ;0=Use 1200 baud
- ;1=Use 2400 baud
- ;2=Use 4800 baud
- ;3=Use 9600 baud
- ;4=Use 19200 baud
- ;5=Use 38400 baud
- DESNOW_FLAG DB 0 ;0=Do not use desnow code
- ;1=Use desnow code
- NULL_MODEM DB 0 ;0=Using a modem
- ;1=Using a null modem cable
- SMILE_FLAG DB 0 ;0=Disable corner smile face
- ;1=Enable corner smile face
- CLEAR_CODE DB 0,2EH ; alt-c, clear code
- EXIT_CODE DB 0,45D ; alt-x, code to exit program
- SHELL_CODE DB 0,1FH ;alt-s, shell to DOS code
- TRANSFER_CODE DB 0,20D ;alt-t, file transfer code
- PASSWORD_SIZE DW EXTRA_PW_SPACE-PASSWORD
- PASSWORD DB "PC MAGAZINE"
- EXTRA_PW_SPACE DB 20-(EXTRA_PW_SPACE-PASSWORD) DUP(?)
- MODEM_SETUP5 DB 30 DUP(0); ;Extra modem setup string
- TONE_DIAL DB "ATDT",0 ;Tone dial command
-
- ;======================================================================
- ; Interrupt handlers. Interrupt 8 is used in unattended mode only.
- ; The communications interrupt is used in both modes.
- ;======================================================================
- ;----------------------------------------------------------------------
- ; Interrupt 8 handling routine. If program is already active do not run.
- ; Run connect unattended if not connected, otherwise run unattended.
- ;----------------------------------------------------------------------
- INT8 PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH DS ;Save data segment
- PUSH CS ;Set data segment to code seg
- POP DS
- PUSHF ;Call old int 8
- CALL DWORD PTR OLDINT_8
- I8_10:
- CLI ;Disable interrupts
- CMP BYTE PTR SLEEP_FLAG,1 ;If another program has control
- JZ I8_EXIT ;then exit
- CMP BYTE PTR ACT_FLAG,0 ;Check for program active
- JNZ I8_EXIT ;Exit if progam is active
- INC BYTE PTR ACT_FLAG ;Set program active flag
- STI ;Enable interrupts
- CALL SET_STACK ;Create stack & save registers
- CMP BYTE PTR CONNECT_FLAG,0 ;Connected to manned?
- JNZ I8_20 ;Yes, then run unattended
- CALL CONNECT_UNATTENDED ;No, check for connection
- JMP I8_30
- I8_20:
- CALL UNATTENDED ;Run unattended
- I8_30:
- CALL RESET_STACK ;Restore registers & stack
- DEC BYTE PTR ACT_FLAG ;Clear program active flag
- I8_EXIT:
- STI ;Enable interrupts
- POP DS ;Restore data segment
- IRET
- INT8 ENDP
-
- ;----------------------------------------------------------------------
- ; Interrupt 21 handling routine. If another program, zcopy, changes
- ; the comm interrupt, go to sleep by setting the sleep flag. When the
- ; comm interrupt vector returns, WAKE UP!
- ;----------------------------------------------------------------------
- INT21 PROC FAR
- PUSHF ;save registers
- PUSH AX
- PUSH BX
- CMP AX,WORD PTR CS:SET_VEC ;setting comm int. vector?
- JZ I21_20 ;yes
- I21_10:
- POP BX ;no, restore registers
- POP AX
- POPF
- JMP DWORD PTR CS:OLDINT_21 ;execute original DOS int
- I21_20:
- MOV AX,CS ;is new code segment
- MOV BX,DS ; the same as pcremote
- CMP AX,BX
- JNZ I21_30 ;no, then go to sleep
- CMP DX,OFFSET CS:INT_COMM ;is it my comm interrupt vec?
- JZ I21_40 ;yes, wake up
- I21_30:
- MOV BYTE PTR CS:SLEEP_FLAG,1 ;I'm getting sleeeeepy
- JMP I21_10
- I21_40:
- POP BX ;restore registers
- POP AX
- STI ;enable interrupts
- CALL DWORD PTR CS:OLDINT_21 ;execute original DOS int vec
- CLI ;disable interrupts
- CALL CLEAR_VIDEO ;clear the screen
- MOV BYTE PTR CS:SLEEP_FLAG,00 ;WAKE UP!
- PUSH DX
- PUSH AX
- PUSH DS ;Save data segment
- PUSH CS ;Set data segment to code seg.
- POP DS
- CALL INIT_SERIAL ;Re-initialize serial port
- CALL CLEAR_OUTBUFF ;Clear buffers because ZCOPY
- CALL CLEAR_INBUFF ; sent hex 02's to sync systems
- POP DS ;Restore the data segment
- POP AX ;Restore registers
- POP DX
- STI ;Enable interrupts
- RET 2 ;Return to calling program
- INT21 ENDP
-
- ;---------------------------------------------------------------------
- ; Clear the video copy to force a new screen to be tranferred to
- ; remote system
- ;---------------------------------------------------------------------
- CLEAR_VIDEO:
- PUSH CX ;Store necessary registers
- PUSH DI
- PUSH ES
- PUSHF
- CLD ;Direction = forward
- PUSH CS ;Push CS so ES can now
- POP ES ; point at it .. ES->CS
- MOV DI,WORD PTR VIDEO_COPY ;ES:DI->Video copy
- MOV AX,720H ;AL=SPACE,AH=Normal attribute
- MOV CX,2000D ;Clear entire video copy
- REP STOSW ;Store char and attribute
- MOV CURSOR_POSITION,0FFFFH ;Reset cursor to be updated
- POPF ;Restore registers
- POP ES
- POP DI
- POP CX
- RET
-
- ;----------------------------------------------------------------------
- ; Interrupt handling routine for communications interrupt. Provides
- ; interrupt driven I/O. Transmit or receive a character.
- ;----------------------------------------------------------------------
- INT_COMM PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH DS ;Save data segment
- PUSH DX ;Save registers
- PUSH BX
- PUSH AX
- PUSH CS ;Set data segment to code seg.
- POP DS
- MOV DX,COMM_PORT ;Get port base address
- INC DX ;Point to int. id reg.
- INC DX
- IN AL,DX ;Get the interrupt id byte
- IC_10:
- CMP AL,2 ;Transmit empty int?
- JZ IC_40 ;Yes transmit a byte
- ;
- ; received data, get it and store in buffer
- ;
- DEC DX ;Port base address
- DEC DX
- IN AL,DX ;Get data from receive register
- MOV BX,IN_BUFF_TAIL ;Get the buffer tail pointer
- MOV [BX],AL ;Store the data in buffer
- INC BX ;Point to next data storage
- CMP IN_BUFF_END,BX ;Beyond end of buffer area?
- JNE IC_20 ;No, then don't reset
- MOV BX,IN_BUFF_BEGIN ;Yes, reset to buffer begin
- IC_20:
- CMP BX,IN_BUFF_HEAD ;Test for buffer full
- JE IC_30 ;If so,don't change ptr ,sorry
- MOV IN_BUFF_TAIL,BX ;Save new tail pointer
- IC_30:
- JMP IC_70
- ;
- ; transmit buffer empty, send a byte
- ;
- IC_40:
- DEC DX ;Port base address
- DEC DX
- MOV BX,OUT_BUFF_HEAD ;Get the buffer head pointer
- CMP BX,OUT_BUFF_TAIL ;Test for data in buffer
- JE IC_60 ;If the same, no data so exit
- MOV AL,[BX] ;Get the data
- INC BX ;Point to next data in buffer
- CMP OUT_BUFF_END,BX ;Beyond end of buffer area?
- JNE IC_50 ;No, then don't reset
- MOV BX,OUT_BUFF_BEGIN ;Yes, reset to buffer begin
- IC_50:
- MOV OUT_BUFF_HEAD,BX ;Save new head pointer
- OUT DX,AL ;Send the data out the port
- JMP IC_70 ;Check for request pending
- IC_60:
- MOV BYTE PTR COMM_INT_STA,0 ;Reset transmitting data flag
- IC_70:
- INC DX ;Point to int. id reg.
- INC DX
- IN AL,DX ;Get the interrupt id byte
- TEST AL,1 ;Request pending?
- JZ IC_10 ;Yes, then process
- IC_EXIT:
- MOV AL,20H ;Reset 8259
- OUT 20H,AL
- STI ;Enable interrupts
- POP AX ;Restore registers
- POP BX
- POP DX
- POP DS ;Restore data segment
- IRET
- INT_COMM ENDP
-
- ;----------------------------------------------------------------------
- ; Create stack area and save all registers.
- ;----------------------------------------------------------------------
- SET_STACK PROC NEAR
- ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
- MOV TEMP_REG,BX ;Save BX
- POP BX ;Save the return address
- PUSH AX ;Save AX
- ;
- ; make my own stack
- ;
- CLI ;Disable interrupts
- MOV AX,SS ;Put old stack segment in AX
- MOV OLD_SS,AX ;And save it
- MOV AX,SP ;Put old stack pointer in AX
- MOV OLD_SP,AX ;And save it
- MOV AX,CS ;Get current segment
- MOV SS,AX ;And put into stack segment
- MOV AX,STACK_TOP ;Get top of stack address
- MOV SP,AX ;And put into stack pointer
- STI ;Enable interrupts
- ;
- ; save all the registers on the stack
- ;
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH BP
- MOV AX,CS ;Get code segment
- MOV DS,AX ;Set data segment to code seg
- MOV ES,AX ;Set extra seg to code seg
- PUSH BX ;Restore return address
- RET
- SET_STACK ENDP
-
- ;----------------------------------------------------------------------
- ; Restore all registers and reset stack
- ;----------------------------------------------------------------------
- RESET_STACK PROC NEAR
- ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
- POP BX ;Save return address
- ;
- ; restore the registers
- ;
- POP BP ;Restore the registers
- POP ES
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- ;
- ; restore the original stack
- ;
- CLI ;Disable interrupts
- MOV AX,OLD_SP ;Get old stack pointer
- MOV SP,AX ;And restore it
- MOV AX,OLD_SS ;Get old stack segment
- MOV SS,AX ;And restore it
- STI ;Enable interrupts
- POP AX ;Restore AX
- PUSH BX ;Put return add back on stack
- MOV BX,TEMP_REG ;Restore BX
- RET
- RESET_STACK ENDP
-
- ;======================================================================
- ; The unattended routine will execute the connect routine to establish
- ; a connection with the manned system. Once connected it will execute
- ; the unattended routine to process incoming data and send any changed
- ; video data to the manned system.
- ;======================================================================
-
- ;----------------------------------------------------------------------
- ; CONNECT_UNATTENDED - Check for ring codes, answer the phone and check
- ; the password. If correct, set connected flag.
- ;----------------------------------------------------------------------
- CONNECT_UNATTENDED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
- MOV BP,SP ;Save stack pointer for exit
- XOR AH,AH ;Use input buffer
- MOV CX,10D ;Number of char to check for CR
- MOV BYTE PTR CR_COUNT,5 ;Number of matches required
- CU_10:
- CALL GET_BUFF_DATA ;Try to get data from buffer
- JC CU_20 ;If data, check for CR code
- JMP CU_40 ;else exit, try another speed
- CU_20:
- CMP AL,CR ;Check for CR code
- JNZ CU_30 ;No so skip over
- MOV BYTE PTR SPEED_COUNT,19 ;it's a CR, so speed is correct
- DEC BYTE PTR CR_COUNT ;Found a match dec count
- JZ CU_70 ;5 out of ten then null connect
- CU_30:
- LOOP CU_10 ;Keep trying
- CU_40:
- DEC BYTE PTR SPEED_COUNT
- JZ CU_50
- JMP CU_EXIT
- CU_50:
- DEC BYTE PTR CURRENT_SPEED ;Try a slower speed
- CMP BYTE PTR CURRENT_SPEED,0FFH ;Out of speeds?
- JNZ CU_60 ;No
- MOV AL,BYTE PTR SPEED_FLAG ;Ran out of speeds, reset
- MOV BYTE PTR CURRENT_SPEED,AL ; to starting speed
- CU_60:
- MOV BYTE PTR SPEED_COUNT,19 ;reset tick counter
- MOV AL,BYTE PTR CURRENT_SPEED ;set the slower speed
- CALL SET_BAUD_RATE
- CALL CLEAR_INBUFF ;Empty the input buffer
- JMP CU_EXIT ;No 5 out of 10, exit
- CU_70:
- MOV BYTE PTR CONNECT_FLAG,1 ;Set connect flag
- MOV CX,3 ;3 tries to enter password
- CU_80:
- MOV SI,OFFSET PASS_MESSAGE ;Point to enter password mess.
- CALL LOAD_ZSTRING ;Load it into output buffer
- CALL GET_PASSWORD ;Get the password
- CALL CHECK_PASSWORD ;Check the password sent
- JZ CU_90 ;Jump if correct
- LOOP CU_80 ;Keep trying
- MOV AL,1 ;Use set up string 2
- MOV BYTE PTR BAD_PASSWORD,1D ;Send exit code
- CALL RESET_MODEM ;Hangup and reset modem
- JMP CU_EXIT ;Done, so exit
- CU_90:
- MOV AH,1 ;Use output buffer
- XOR AL,AL ;Sync byte to send
- MOV CX,5 ;Send 5 of them
- CU_100:
- CALL PUT_BUFF_DATA ;Send them
- LOOP CU_100
- ;
- ; Notify remote computer the value of host's COMM_FLAG switch. This allows
- ; the remote computer to properly send the ZCOPY command line to the host.
- ;
- MOV AH,1 ;Use output buffer
- MOV AL,BYTE PTR COMM_FLAG ;Send host's comm port
- INC AL ;Bump AL so sent byte will be
- ; in range from 1 thru 4.
- MOV CX,10D ;Send 10 of them
- CU_110:
- CALL PUT_BUFF_DATA ;Send Host Comm Port
- LOOP CU_110 ;Sent 10 ?
- XOR AL,AL ;Sync byte to send
- MOV CX,5D ;Send 5 of them
- CU_120:
- CALL PUT_BUFF_DATA ;Send sync byte
- LOOP CU_120 ;Sent 5 ?
- CU_EXIT:
- RET
- CONNECT_UNATTENDED ENDP
-
- ;----------------------------------------------------------------------
- ; Get the password from the manned system
- ; Input - Nothing
- ; Output - Password buffer contains password from manned system
- ; Changes - DI, AX
- ;----------------------------------------------------------------------
- GET_PASSWORD PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
- PUSH CX ;Save register
- MOV DI,OFFSET PASSWORD_BUFFER ;Point to password buffer
- MOV CX,20D ;Zero buffer to clear previous
- XOR AL,AL ; password
- CLD
- REP STOSB
- MOV DI,OFFSET PASSWORD_BUFFER ;Pointer to buffer
- MOV CX,20D ;Maximum password size
- GP_10:
- CALL CHECK_CARRIER ;Check for carrier loss
- JNZ GP_20
- JMP IP_90 ;Carrier loss, reset and exit
- GP_20:
- CALL INPUT_PROCESSING ;Get data & put in keybd buffer
- CALL GET_KEYSTROKE ;Check for keystroke
- JZ GP_10 ;None, so wait
- CMP AL,60H ;Check for lower case
- JL GP_30 ;No then leave it alone
- AND AL,5FH ;Convert to upper case
- GP_30:
- CMP AL,CR ;If it is a CR then exit
- JZ GP_EXIT
- CMP AL,BS ;Is it a back space?
- JNZ GP_40 ;No, so save it
- INC CX ;Resetcounter for BS
- CMP DI,OFFSET PASSWORD_BUFFER ;Already at start of buffer?
- JZ GP_60 ;Yes, then don't backspace
- DEC DI ;Backspace buffer pointer
- MOV BYTE PTR [DI],0 ; and null the data
- JMP GP_50
- GP_40:
- CLD ;Forward
- STOSB ;Save the character
- MOV AL,'*' ;Echo character
- GP_50:
- MOV AH,1 ;Use output buffer
- CALL PUT_BUFF_DATA ; and store the character
- GP_60:
- LOOP GP_10 ;Receive up to CX characters
- GP_EXIT:
- POP CX ;Restore register
- RET
- GET_PASSWORD ENDP
-
- ;----------------------------------------------------------------------
- ; Check the password in the buffer with correct password
- ; Input - Nothing
- ; Output - Zero set - correct password
- ; Zero reset - Wrong password
- ; Changes - SI, DI
- ;----------------------------------------------------------------------
- CHECK_PASSWORD PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
- PUSH CX ;Save register
- MOV SI,OFFSET PASSWORD_BUFFER ;Pointer to buffer
- MOV DI,OFFSET PASSWORD ;Pointer to password
- MOV CX,PASSWORD_SIZE ;Number of compares to make
- CLD ;Compare forward
- REPZ CMPSB ;Repeat while passwords match
- POP CX ;Restore register
- RET
- CHECK_PASSWORD ENDP
-
- ;----------------------------------------------------------------------
- ; UNATTENDED - Process incoming data and check for changes in video
- ; data, format and send to manned system. Maintains 18 or less characters
- ; in output buffer, ensures maximum throughput.
- ;----------------------------------------------------------------------
- UNATTENDED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
- MOV BP,SP ;Save stack pointer for exit
- CALL INPUT_PROCESSING ;Process any buffered data
- ;
- ; Check for a change in the cursor position
- ;
- PUSH ES
- MOV AX,40H ;Set ES to BIOS data segment
- MOV ES,AX
- MOV BX,ES:[50H] ;Get current cursor position
- CMP BX,CURSOR_POSITION ;Compare with copy
- JZ UA_10 ;No change, skip
- MOV CURSOR_POSITION,BX ;Save new cursor position
- MOV AL,0D2H ;Sync bits, set position
- MOV AH,1 ;Use output buffer
- CALL PUT_BUFF_DATA ;Send sync byte
- MOV AL,BL ;Low byte
- CALL PUT_BUFF_DATA
- MOV AL,BH ;High byte
- CALL PUT_BUFF_DATA
- UA_10:
- POP ES ;Restore ES
- CMP BYTE PTR SMILE_FLAG,0 ;Smile face enabled ?
- JE UA_20 ;No, skip smile face coding
- ;
- ; Redisplay the smile face in upper right corner
- ;
- PUSH ES ;Store ES
- MOV AX,VIDEO_SEGMENT ;AX = Video Segment
- MOV ES,AX ;ES = Video Segment
- MOV DI,158D ;DI-> Upper right corner
- MOV AL,01H ;Smiley Face code
- CALL PUT_VIDEO_DATA ;Write Video RAM
- POP ES ;Restore ES
- UA_20:
- MOV VID_RAM_OFFSET,0 ;Start at address 0
- MOV BYTE PTR BLOCK_COUNT,0 ;Reset block counter
- ;
- ; Check the output buffer and keep it full enough so it's busy till
- ; next timer tick.
- ;
- UA_30:
- MOV AX,7 ;1200 baud, at least 7 bytes
- MOV CL,BYTE PTR CURRENT_SPEED ;the speed decides the size
- SHL AX,CL ;larger for faster baud
- MOV CX,AX ;at least this many bytes
- CLI
- MOV AX,OUT_BUFF_HEAD ;Get the head pointer
- MOV BX,OUT_BUFF_TAIL ;Get the tail pointer
- STI
- UA_40:
- CMP AX,BX ;Less than bytes in buffer
- JZ UA_60 ;Yes, check the video data
- INC AX ;Increment head pointer
- CMP OUT_BUFF_END,AX ;Beyond end of buffer area?
- JNE UA_50 ;No, then don't reset
- MOV AX,OUT_BUFF_BEGIN ;Yes, reset to buffer begin
- UA_50:
- LOOP UA_40 ;Check all the bytes
- JMP UA_EXIT ;More than allowed, exit
- ;
- ; compare the video copy with the video ram
- ;
- UA_60:
- PUSH DS ;Save data segment
- MOV SI,VID_RAM_OFFSET ;Get the current offset
- MOV DI,TEMP_VIDEO_PTR ;Dest. ES:DI temp video buffer
- MOV AX,VIDEO_SEGMENT ;Get video Segment register
- MOV DS,AX ;Source DS:SI video RAM
- ;
- ; transfer block_size words of data from video RAM to the temp buffer
- ;
- MOV CX,BLOCK_SIZE ;Get count of words to transfer
- CLD
- CMP BYTE PTR CS:DESNOW_FLAG,0 ;Check desnow flag
- JZ UA_90
- SAL CX,1 ;Convert words to bytes
- MOV DX,3DAH ;CGA status port
- UA_70:
- IN AL,DX ;Get status byte
- TEST AL,1 ;Test display enable
- JNZ UA_70 ;If in Hor. sync then wait
- CLI ;Disable interrupts
- UA_80:
- IN AL,DX ;Get status byte
- TEST AL,1 ;Test display enable
- JZ UA_80 ;Wait for Hor. sync
- MOVSB ;Transfer one byte
- STI ;Enable interrupts
- LOOP UA_70 ;Transfer block size words
- JMP UA_100
- UA_90:
- REP MOVSW
- UA_100:
- POP DS ;Restore data segment
- ;
- ; compare the block from video RAM with the video copy
- ;
- MOV CX,BLOCK_SIZEX2 ;Number of words to compare
- MOV SI,TEMP_VIDEO_PTR ;Point to block of video data
- MOV DI,VIDEO_COPY ;Point to video copy
- ADD DI,VID_RAM_OFFSET ;Adjust for current block
- REPE CMPSB ;Compare while equal
- JNE UA_110 ;No match, format & send block
- MOV AX,VID_RAM_OFFSET ;Get current block pointer
- ADD AX,BLOCK_SIZEX2 ;Point to next block
- MOV VID_RAM_OFFSET,AX ;And save the pointer
- INC BYTE PTR BLOCK_COUNT ;Increment current block count
- CMP AX,4000D ;Check for end of video RAM
- JNZ UA_60 ;No, keep checking the RAM
- JMP UA_EXIT ;then exit
- ;
- ; data doesn't match, format and send to manned system
- ;
- UA_110:
- INC CX ;Adjust count
- AND CX,1 ;LSB indicates char or attr.
- CALL TRANSFER_BLOCK ;Prepare to send block of data
- JMP UA_30 ;Again, till buffer is full
- UA_EXIT:
- RET
- UNATTENDED ENDP
-
- ;----------------------------------------------------------------------
- ; Get data from the unattended input buffer and process
- ; Input - Nothing
- ; Output - Keyboard buffer or shift status is updated
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- INPUT_PROCESSING PROC NEAR
- PUSH AX ;Save register
- PUSH DX
- PUSH ES
- MOV AX,40H ;Set ES to BIOS data area
- MOV ES,AX
- IP_10:
- CMP BYTE PTR CONNECT_FLAG,0 ;Are we connected
- JZ IP_20 ;No, don't check carrier
- CALL CHECK_CARRIER ;Yes check for carrier loss
- JZ IP_90 ;Carrier loss, reset and exit
- ;
- ; make sure there is room in the keyboard buffer for a keystroke
- ;
- IP_20:
- CLI ;Don't allow interrupts
- MOV AX,ES:[1CH] ;Get the buffer tail pointer
- INC AX ;Point to next data storage
- INC AX
- CMP AX,3EH ;Beyond end of buffer area?
- JNE IP_30 ;No, then don't reset
- MOV AX,1EH ;Yes, reset to buffer begin
- IP_30:
- CMP AX,ES:[1AH] ;Test for buffer full
- JE IP_40 ;If the same, don't process key
- STI
- JMP IP_50 ;Process incoming keystrokes
- IP_40:
- STI ;Enable interrupts
- JMP IP_EXIT ;Exit the routine
- IP_50:
- MOV AH,0 ;Use input buffer
- CALL GET_BUFF_DATA ;Get a byte of data
- JC IP_60 ;If data then process
- JMP IP_EXIT ;Otherwise exit
- ;
- ; Check to see if expecting ASCII data
- ;
- IP_60:
- CMP ASCII_FLAG,0 ;Check ASCII flag
- JNZ IP_70 ;
- JMP IP_120 ; 0=not expecting data here
- IP_70:
- CMP ASCII_FLAG,1 ;Check for received 1st byte
- JNZ IP_80 ;Jump if second byte
- MOV KEY_ONE,AL ;Save scan code, byte one
- INC BYTE PTR ASCII_FLAG ;Indicate receiving one byte
- JMP IP_10 ;Process next byte
- IP_80:
- MOV KEY_TWO,AL ;Save ASCII code, byte two
- MOV AL,KEY_ONE ;Get ASCII code
- MOV AH,KEY_TWO ;Get scan code
- CMP AX,WORD PTR EXIT_CODE ;Check for exit code
- JNZ IP_100 ;No,then continue processing
- IP_90: ;Otherwise reset connect & exit
- CMP BYTE PTR SMILE_FLAG,0 ;Smile flag set ?
- JE IP_95 ;No, skip resetting smile face
- PUSH AX ;Store AX
- PUSH ES ;Store ES
- PUSH DI ;Store DI
- MOV AX,VIDEO_SEGMENT ;AX = VIDEO_SEGMENT
- MOV ES,AX ;ES = VIDEO_SEGMENT
- MOV DI,158D ;Bump DI 79 chars
- MOV AL,SPACE ;Blank space
- CALL PUT_VIDEO_DATA ;Write Video RAM
- POP DI ;Restore DI
- POP ES ;Restore ES
- POP AX ;Restore AX
- IP_95:
- CALL CLEAR_INBUFF ;Clear input buffer
- CALL CLEAR_OUTBUFF ;Clear output buffer
- MOV BYTE PTR COMM_INT_STA,0 ;Reset transmitting data flag
- CALL IU_10 ;reinit and reset modem
- CLI ;Disable interrupts
- MOV BYTE PTR CONNECT_FLAG,0 ;Reset the connect flag
- MOV BYTE PTR ASCII_FLAG,0 ;Reset ASCII flag
- MOV BYTE PTR SHIFT_FLAG,0 ;Reset shift flag
- MOV BYTE PTR ES:[17H],0 ;Reset any shift status
- MOV SP,BP ;Clean the stack
- RET ;And exit unattended routine
- IP_100:
- CMP AX,WORD PTR CLEAR_CODE ;Clear code received
- JNZ IP_110 ;No... skip clear code coding
- CALL CLEAR_VIDEO ;Rewrite screen
- MOV BYTE PTR ASCII_FLAG,0 ;Reset ASCII flag
- JMP IP_10 ;Get next character
- IP_110: ;
- CALL PUT_KEY_DATA ;And stuff in keyboard buffer
- MOV BYTE PTR ASCII_FLAG,0 ;Reset ASCII flag for next data
- JMP IP_10 ;Process next byte
- ;
- ; Check to see if expecting shift data
- ;
- IP_120:
- CMP BYTE PTR SHIFT_FLAG,0 ;Check shift flag
- JZ IP_130 ;0=not expecting data here
- MOV ES:[17H],AL ;And save in shift status
- MOV BYTE PTR SHIFT_FLAG,0 ;Reset shift flag for next data
- JMP IP_10 ;Process next byte
- ;
- ; Check to see if it's a sync byte
- ;
- IP_130:
- CMP AL,0FEH ;Check for ASCII sync byte
- JNZ IP_140 ;If not then check for shift
- INC BYTE PTR ASCII_FLAG ;Indicate received FEh
- JMP IP_10 ;Process next byte
- IP_140:
- CMP AL,0FDH ;Check for shift sync byte
- JNZ IP_150 ;If not then throw away
- INC BYTE PTR SHIFT_FLAG ;Indicate received FDh
- IP_150:
- JMP IP_10 ;Process till buffer empty
- IP_EXIT:
- POP ES ;Restore registers
- POP DX
- POP AX
- RET
- INPUT_PROCESSING ENDP
-
- ;----------------------------------------------------------------------
- ; Formats the data in temporary video buffer and puts it into the
- ; output buffer
- ; Input - CX=0 Transfer character data to output buffer
- ; CX=1 Transfer attribute data to output buffer
- ; Output - Nothing
- ; Changes - AX, BX, CX, SI, DI
- ;----------------------------------------------------------------------
- TRANSFER_BLOCK PROC NEAR
- PUSH CX ;Save the data type
- ;
- ; If the data is all the same only send it once, and set the repeat flag
- ;
- MOV SI,TEMP_VIDEO_PTR ;Point
- ADD SI,CX ;Adjust for char. or attr.
- XOR BL,BL ;Initialize for non-repeating
- MOV CX,BLOCK_SIZE ;Number of bytes to compare
- MOV AH,[SI] ;Get the first byte in block
- TB_10:
- LODSB ;Get next byte from the block
- INC SI ;Adjust for word
- CMP AH,AL ;Verify all the same
- LOOPZ TB_10 ;For the entire block
- JNZ TB_20 ;Not the same, send block
- MOV BL,2 ;set repeat flag
- TB_20:
- POP CX ;Restore data type
- MOV AL,0FCH ;Start with base sync byte
- OR AL,CL ;Include data type bit
- OR AL,BL ;Include repeat bit
- MOV AH,1 ;Use output buffer
- CALL PUT_BUFF_DATA ;Put sync byte in output buff.
- MOV AL,BLOCK_COUNT
- MOV AH,1 ;Use output buffer
- CALL PUT_BUFF_DATA ;Send the block number
- MOV SI,TEMP_VIDEO_PTR ;Point to block of video data
- ADD SI,CX ;Adjust for char. or attr.
- MOV DI,VIDEO_COPY ;Point to video copy
- ADD DI,VID_RAM_OFFSET ;Adjust for block offset
- ADD DI,CX ; and character or attribute
- MOV CX,BLOCK_SIZE ;Number of bytes to send
- CLD ;Forward direction
- TB_30:
- LODSW ;Get the unmatched data
- OR BL,BL ;Check the repeat flag
- JNZ TB_40 ;Don't send repeat data
- MOV AH,1 ;Use the output buffer
- CALL PUT_BUFF_DATA ;Put the video data in out buff
- TB_40:
- STOSB ;Save video data in copy
- INC DI ;Adjust for word offset
- LOOP TB_30 ;Send block size bytes of data
- OR BL,BL ;If repeat data then send one
- JZ TB_50
- MOV AH,1
- CALL PUT_BUFF_DATA
- TB_50:
- RET
- TRANSFER_BLOCK ENDP
-
- ;----------------------------------------------------------------------
- ; Put a byte of data into the unattended keyboard buffer.
- ; Input - AL contains ASCII to be put into buffer.
- ; AH contains scan code to be put into buffer.
- ; Output - Carry Set - Byte placed in buffer successfully
- ; Carry Reset - Buffer full, byte not stored in buffer
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- PUT_KEY_DATA PROC NEAR
- PUSH BX ;Save registers
- PUSH SI
- PUSH DI
- MOV SI,1AH ;Point to keyboard head pointer
- CLI ;Don't allow interrupts
- MOV BX,ES:[1CH] ;Get the buffer tail pointer
- MOV DI,BX ;Save the tail pointer
- INC BX ;Point to next data storage
- INC BX
- CMP BX,3EH ;Beyond end of buffer area?
- JNE PK_10 ;No, then don't reset
- MOV BX,1EH ;Yes, reset to buffer begin
- PK_10:
- CMP BX,ES:[1AH] ;Test for buffer full
- JE PK_EXIT ;If the same, don't save it
- ; exit, carry is already reset
- MOV ES:[DI],AX ;Store the data in buffer
- MOV ES:[1CH],BX ;Save new tail pointer
- STC ;Indicate data stored OK
- PK_EXIT:
- POP DI
- POP SI
- POP BX
- STI ;Enable interrupts
- RET
- PUT_KEY_DATA ENDP
-
- ;======================================================================
- ; COMMON ROUTINES - These routines are common to both the unattended
- ; processing portion of the program and the manned processing portion.
- ;======================================================================
-
- ;----------------------------------------------------------------------
- ; Store the video data in AL in the memory location pointed to by DI
- ; INPUT - AL video data, ES:DI video RAM destination
- ; OUTPUT - Nothing
- ; Changes - DI is incremented
- ;----------------------------------------------------------------------
- PUT_VIDEO_DATA PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- ;
- ; Check desnow flag, if set wait for horizontal sync to put in video RAM
- ;
- PUSH BX ; Save Registers
- PUSH DX
- CMP BYTE PTR DESNOW_FLAG,0 ; Check Desnow flag
- JZ PV_30 ; No, skip over
- CLD ; Forward
- XCHG AX,BX ; Save video data
- MOV DX,3DAH ; CGA status port
- PV_10:
- IN AL,DX ; Get status byte
- TEST AL,1 ; Test display enable
- JNZ PV_10 ; If in Hor. sync, wait
- PV_20:
- IN AL,DX ; Get status byte
- TEST AL,1 ; Test display enable
- JZ PV_20 ; Wait for Hor. sync
- XCHG AX,BX ; Get video data
- PV_30:
- STOSB ; Put into video RAM
- POP DX ; Restore registers
- POP BX
- RET
- PUT_VIDEO_DATA ENDP
-
- ;----------------------------------------------------------------------
- ; Get a byte of data from a buffer. Byte pointed to by head pointer is
- ; is next data byte. If head=tail, no data in buffer.
- ; Input - AH - Buffer to use 0=Input buffer, 1=Output buffer.
- ; Output - Carry Set - Byte from buffer is in AL
- ; Carry Reset - No data in buffer
- ; Changes - AL
- ;----------------------------------------------------------------------
- GET_BUFF_DATA PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH BX ;Save registers
- PUSH SI
- CMP AH,0 ;Check which buffer to use
- JNZ GD_10 ;Jump for output buffer
- MOV SI,OFFSET IN_BUFF_HEAD ;Point to input buffer
- JMP GD_20 ;Skip over out buffer
- GD_10:
- MOV SI,OFFSET OUT_BUFF_HEAD ;Point to output buffer
- GD_20:
- CLI ;Don't allow interrupts
- MOV BX,[SI] ;Get the buffer head pointer
- CMP BX,2[SI] ;Test for data in buffer
- JE GD_EXIT ;If the same, no data so
- ; exit, carry is already reset
- MOV AL,[BX] ;Get the data
- INC BX ;Point to data in buffer
- CMP 6[SI],BX ;Beyond end of buffer area?
- JNE GD_30 ;No, then don't reset
- MOV BX,4[SI] ;Yes, reset to buffer begin
- GD_30:
- MOV [SI],BX ;Save new head pointer
- STC ;Indicate data is in AL
- GD_EXIT:
- POP SI ;Restore registers
- POP BX
- STI ;Enable interrupts
- RET
- GET_BUFF_DATA ENDP
-
- ;----------------------------------------------------------------------
- ; Put a byte of data into a buffer. Byte is stored at location
- ; pointed to by tail pointer.
- ; Input - AL contains data to be put into buffer.
- ; AH - Buffer to use 0=Input buffer, 1=Output buffer
- ; Output - Carry Set - byte placed in buffer successfully
- ; Carry Reset - Buffer full, byte not stored in buffer
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- PUT_BUFF_DATA PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save registers
- PUSH BX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH CS ;Set data segment to CS
- POP DS
- CMP AH,0 ;Check which buffer to use
- JNZ PD_10 ;Jump for output buffer
- MOV SI,OFFSET IN_BUFF_HEAD ;Point to input buffer
- JMP PD_20 ;Skip over out buffer
- PD_10:
- MOV SI,OFFSET OUT_BUFF_HEAD ;Point to output buffer
- PD_20:
- CLI ;Don't allow interrupts
- MOV BX,2[SI] ;Get the buffer tail pointer
- MOV DI,BX ;Save the tail pointer
- INC BX ;Point to next data storage
- CMP 6[SI],BX ;Beyond end of buffer area?
- JNE PD_30 ;No, then don't reset
- MOV BX,4[SI] ;Yes, reset to buffer begin
- PD_30:
- CMP BX,[SI] ;Test for buffer full
- JE PD_40 ;If so, exit carry is reset
-
- MOV [DI],AL ;Store the data in buffer
- MOV 2[SI],BX ;Save new tail pointer
- STC ;Indicate data stored ok
- PD_40:
- PUSHF ;Save the flags
- CMP BYTE PTR COMM_INT_STA,0 ;Transmit int. running?
- JNZ PD_60 ;Yes, so exit
- MOV AX,OUT_BUFF_HEAD ;Is data in output buffer
- CMP AX,OUT_BUFF_TAIL
- JZ PD_60 ;No, so exit
- MOV BYTE PTR COMM_INT_STA,1 ;Set transmitting data flag
- MOV DX,COMM_PORT ;Get port base address
- ADD DX,5 ;Line status register
- PD_50:
- IN AL,DX ;Make sure holding reg. empty
- TEST AL,00100000B ;Test the hold reg empty flag
- JZ PD_50 ;Loop if not empty
- SUB DX,5 ;Port base register
- MOV AH,1 ;Use the output buffer
- CALL GET_BUFF_DATA ;Get data from output buffer
- OUT DX,AL ;Send the data out the port
- PD_60:
- STI ;Enable interrupts
- POPF ;Restore flags
- POP DS ;Restore registers
- POP DI
- POP SI
- POP DX
- POP BX
- POP AX
- RET
- PUT_BUFF_DATA ENDP
-
- ;----------------------------------------------------------------------
- ; Clear the input buffer
- ; Input - Nothing
- ; Output - Nothing
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- CLEAR_INBUFF PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save register
- CLI ;Disable interrupts
- MOV AX,IN_BUFF_TAIL ;Get buffer tail pointer
- MOV IN_BUFF_HEAD,AX ;Make head equal tail
- STI ;Enable interrupts
- POP AX
- RET
- CLEAR_INBUFF ENDP
-
- ;----------------------------------------------------------------------
- ; Clear the output buffer
- ; Input - Nothing
- ; Output - Nothing
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- CLEAR_OUTBUFF PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save register
- CLI ;Disable interrupts
- MOV AX,OUT_BUFF_TAIL ;Get buffer tail pointer
- MOV OUT_BUFF_HEAD,AX ;Make head equal tail
- STI ;Enable interrupts
- POP AX
- RET
- CLEAR_OUTBUFF ENDP
-
- ;----------------------------------------------------------------------
- ; Reset the modem and send the setup string to initialize
- ; Input - AL - 0 use setup string 1, 1 use setup string 2
- ; Output - Nothing
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- RESET_MODEM PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- CMP BYTE PTR NULL_MODEM,0 ;If null modem don't reset
- JZ RM_10
- MOV BYTE PTR CONNECT_FLAG,0 ;Reset connect flag
- ;
- ; After resetting connect flag, see if unattended and three bad passwords
- ; received, if so send an exit code to the remote computer so that the
- ; remote computer can exit to DOS.
- ;
- CMP BYTE PTR MANNED_FLAG,0 ;If host, then send exit code
- JNE RM_5 ; to remote system to exit
- CMP BYTE PTR BAD_PASSWORD,0 ;Three bad passwords ?
- JE RM_5 ;No, skip sending exit code
- CALL CLEAR_OUTBUFF ;Clear out buff to insure room
- MOV AX,WORD PTR EXIT_CODE ;Set up AL and AH to send
- MOV AL,AH ; the exit code thru out buff.
- MOV AH,1 ;Use output buffer
- CALL PUT_BUFF_DATA ;Send char (exit_code)
- RM_5: ;
- JMP RM_EXIT ;and return to caller
- RM_10:
- PUSH SI ;Save registers
- PUSH DX
- PUSH AX
- CMP BYTE PTR CONNECT_FLAG,0 ;Is modem connected?
- JZ RM_20 ;No then send setup only
- CALL CLEAR_OUTBUFF ;Empty the output buffer
- MOV BYTE PTR CONNECT_FLAG,0 ;Reset connect flag
- MOV AL,1 ;Wait a second for guard time
- CALL DELAY
- MOV SI,OFFSET MODEM_ESCAPE ;Send modem escape code
- CALL LOAD_ZSTRING
- MOV AL,2 ;Wait
- CALL DELAY
- MOV SI,OFFSET MODEM_HANGUP ;Send modem hangup code
- CALL LOAD_ZSTRING
- MOV AL,1 ;Wait for a second
- CALL DELAY
- RM_20:
- MOV AL,SPEED_FLAG ;Get speed flag
- MOV BYTE PTR CURRENT_SPEED,AL ;Save as next starting speed
- CALL SET_BAUD_RATE
- MOV BYTE PTR SPEED_COUNT,19
- MOV SI,OFFSET MODEM_ATTENTION ;Point to modem attention
- CALL LOAD_ZSTRING ;Put it into output buffer
- MOV AL,1 ;Wait for a second
- CALL DELAY
- POP AX ;Get setup string to use
- CMP AL,0 ;Test for string 1
- JNZ RM_30 ;No, then use string 2
- MOV SI,OFFSET MODEM_SETUP1 ;Point to modem setup string 1
- JMP RM_40
- RM_30:
- MOV SI,OFFSET MODEM_SETUP2 ;Point to modem setup string 2
- RM_40:
- CALL LOAD_ZSTRING ;Load setup string to modem
- MOV AL,1 ;Wait a second
- CALL DELAY
- MOV SI,OFFSET MODEM_SETUP3 ;Point to modem setup string 3
- CALL LOAD_ZSTRING ;Load setup string to modem
- CMP BYTE PTR SPEED_FLAG,2 ;If speed is 1200 or 2400
- JL RM_50 ; skip setup string 4
- MOV AL,1 ;Wait a second
- CALL DELAY
- MOV SI,OFFSET MODEM_SETUP4 ;Point to modem setup string 4
- CALL LOAD_ZSTRING ;Load setup string to modem
- RM_50:
- MOV AL,1 ;Wait a second
- CALL DELAY
- MOV SI,OFFSET MODEM_SETUP5 ;Point to custom setup string 5
- CALL LOAD_ZSTRING ;Load setup string to modem
- CALL CLEAR_INBUFF ;Clear the input buffer
- POP DX ;Restore registers
- POP SI
- RM_EXIT:
- RET
- RESET_MODEM ENDP
-
- ;----------------------------------------------------------------------
- ; Check carrier reads the carrier status signal and sets Z flag to
- ; indicate status
- ; Input - Nothing
- ; Output - Zero flag 0 - Carrier
- ; Zero flag 1 - No Carrier detected
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- CHECK_CARRIER PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save registers
- CMP BYTE PTR NULL_MODEM,0 ;If null modem don't reset
- JZ CC_10
- CMP BYTE PTR CONNECT_FLAG,0 ;
- JZ CC_EXIT ;not connected, send no carrier
- MOV AH,1 ;reset zero flag
- CMP AH,0
- JMP CC_EXIT ;and return to caller
- CC_10:
- PUSH DX
- MOV DX,COMM_PORT ;Get the comm base address
- ADD DX,6 ;Modem status register
- IN AL,DX ;Get the current status
- TEST AL,10000000B ;Data carrier detect
- POP DX ;Restore registers
- CC_EXIT:
- POP AX
- RET
- CHECK_CARRIER ENDP
-
- ;----------------------------------------------------------------------
- ; DELAY - delay approximate number of seconds in AL
- ; Input - AL
- ; Output - Nothing (just waits till AL is zero)
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- DELAY PROC NEAR
- PUSH CX ;Save registers
- PUSH DX
- PUSH DI
- PUSH AX
- XOR AH,AH ;Read system time
- INT 1AH
- STI ;Enable interrupts Ver 1.1
- MOV DI,DX ;Save low tick count
- MOV SI,CX ;Save high tick count
- POP AX ;Get number of seconds to delay
- PUSH AX
- XOR CX,CX ;Zero CX
- MOV CL,AL ;Put seconds into loop counter
- D_10:
- ADD DI,19D ;Approximate counts in a second
- ADC SI,0 ;Add carry to SI
- LOOP D_10
- D_20:
- XOR AH,AH ;Read system time
- INT 1AH
- STI ;Enable interrupts Ver 1.1
- CMP SI,CX
- JNE D_20
- CMP DI,DX ;End of delay time
- JGE D_20 ;No, keep checking
- POP AX ;Restore registers
- POP DI
- POP DX
- POP CX
- RET
- DELAY ENDP
-
- ;----------------------------------------------------------------------
- ; String at SI is placed in output buffer to be sent out serial port
- ; Input - SI points to zero terminated string
- ; Output - Nothing
- ; Changes - SI
- ;----------------------------------------------------------------------
- LOAD_ZSTRING PROC NEAR
- PUSH AX ;Save register
- MOV AH,1 ;Use output buffer
- CLD ;Forward
- LZ_10:
- LODSB ;Get a byte of data
- CMP AL,0 ;Check for zero
- JZ LZ_EXIT ;Yes, then exit
- CALL PUT_BUFF_DATA ;No, put in output buffer
- JMP LZ_10 ;Process next data
- LZ_EXIT:
- POP AX ;Restore register
- RET
- LOAD_ZSTRING ENDP
-
- ;----------------------------------------------------------------------
- ; Check for a key in the keyboard buffer, if one is there, get it
- ; Input - Nothing
- ; Output - Zero flag = 1 no key in buffer
- ; Zero flag = 0 key is in AX
- ; Changes - AX
- ;----------------------------------------------------------------------
- GET_KEYSTROKE PROC NEAR
- ASSUME CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
- MOV AH,1 ;Check for keystroke
- INT 16H ;Keyboard BIOS
- JZ GK_EXIT ;No key so exit
- PUSHF ;Save the zero flag
- XOR AH,AH ;Get the keystroke
- INT 16H
- POPF ;Restore the zero flag
- GK_EXIT:
- RET
- GET_KEYSTROKE ENDP
-
- ;----------------------------------------------------------------------
- ; Initialize the buffer pointers for the input and output buffers.
- ; Input - CX points to starting buffer location
- ; Output - Input and output buffer points are initialized
- ; Changes - BX, CX
- ;----------------------------------------------------------------------
- INIT_BUFFERS PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV BX,OFFSET IN_BUFF_HEAD ;In buffer will be here
- MOV WORD PTR [BX],CX ; Set head pointer to buffer
- MOV WORD PTR 2[BX],CX ;Set tail pointer to buffer
- MOV WORD PTR 4[BX],CX ;Set begin of buffer
- ADD CX,IN_BUFF_SIZE ;CX Points to end of in buffer
- IB_10:
- MOV WORD PTR 6[BX],CX ;Set end of buffer
- MOV BX,OFFSET OUT_BUFF_HEAD ;Out buffer after in buffer
- MOV WORD PTR [BX],CX ; Set head pointer to buffer
- MOV WORD PTR 2[BX],CX ;Set tail pointer to buffer
- MOV WORD PTR 4[BX],CX ;Set begin of buffer
- ADD CX,OUT_BUFF_SIZE ;CX Points to end of out buffer
- MOV WORD PTR 6[BX],CX ;Set end of buffer
- RET
- INIT_BUFFERS ENDP
-
- ;----------------------------------------------------------------------
- ; Change the interrupt 8 vector to the interrupt service routine of
- ; PCREMOTE
- ; Input - Nothing
- ; Output - Interrupt vector 8 points to INT8
- ; Changes - AX, DX, BX, ES
- ;----------------------------------------------------------------------
- MODIFY_INT8 PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- ;
- ; Change interrupt 8 vector
- ;
- MOV AX,3508H ;Get interrupt 8h vector
- INT 21H
- MOV OLDINT_8,BX ;And save it
- MOV OLDINT_8[2],ES
- MOV AX,2508H ;Set interrupt 8h vector
- MOV DX,OFFSET INT8 ; to point to new routine
- INT 21H
- RET
- MODIFY_INT8 ENDP
-
- ;----------------------------------------------------------------------
- ; Change the interrupt 21 vector to the interrupt service routine of
- ; PCREMOTE
- ; Input - Nothing
- ; Output - Interrupt vector 21 points to INT21
- ; Changes - AX, DX, BX, ES
- ;----------------------------------------------------------------------
- MODIFY_INT21 PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AX,3521H ;Get interrupt 21H vector
- INT 21H
- MOV WORD PTR OLDINT_21,BX ;And save it
- MOV WORD PTR OLDINT_21[2],ES
- MOV AX,2521H ;Set interrupt 21H vector
- MOV DX,OFFSET INT21 ; to point to new routine
- INT 21H
- RET
- MODIFY_INT21 ENDP
-
- ;----------------------------------------------------------------------
- ; Change the communication interrupt vector to the interrupt service
- ; routine of PCREMOTE
- ; Input - SET_VEC contains interrupt vector number
- ; Output - communications interrupt vector points to INT_COMM
- ; Changes - AX, DX, BX, ES
- ;----------------------------------------------------------------------
- MODIFY_INTCOMM PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH ES
- MOV AL,BYTE PTR SET_VEC ;Get the interrupt number
- MOV AH,35H ;Get the old vector
- INT 21H
- MOV WORD PTR OLDINT_COMM,BX ;And save it
- MOV WORD PTR OLDINT_COMM[2],ES
- POP ES
- MOV AL,BYTE PTR SET_VEC ;Get the interrupt number
- MOV AH,25H ;Set interrupt for comm vector
- MOV DX,OFFSET INT_COMM ; to point to new routine
- INT 21H
- RET
- MODIFY_INTCOMM ENDP
-
- ;----------------------------------------------------------------------
- ; Set baud rate
- ; Input - AL -0 1200 baud, 1 2400 baud, 2 4800 baud, 3 9600 baud
- ; 4 19200 baud, 5 38400 baud
- ; Output - Nothing
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- SET_BAUD_RATE PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH DX ;Save registers
- PUSH BX
- PUSH SI
- PUSH AX
- MOV DX,COMM_PORT ;Get port address
- ADD DX,3 ;Line control register
- MOV AL,83H ;Toggle port address to
- OUT DX,AL ; prepare to set baud rate
- SUB DX,2 ;Baud rate divisor MSB port
- POP AX ;Restore baud rate
- PUSH AX
- XOR AH,AH ;Zero AH
- MOV SI,AX ;Save in index register
- SHL SI,1 ;Multiply by 2, word address
- MOV BX,OFFSET BAUD_RATE ;Point to baud rates
- MOV AL,[BX+SI] ;Get baud rate MSB
- OUT DX,AL ; and set it
- DEC DX ;Baud rate divisor LSB port
- MOV AL,1[BX+SI] ;Get baud rate LSB
- OUT DX,AL ; and set it
- ADD DX,3 ;Line control register
- MOV AL,3 ;8 data bits,1 stop,no parity
- OUT DX,AL ;Set data bit pattern
- ; and toggle port address
- POP AX ;Restore registers
- POP SI
- POP BX
- POP DX
- RET
- SET_BAUD_RATE ENDP
-
- ;----------------------------------------------------------------------
- ; Initialize the serial port
- ; Input - COMM_PORT contains port address,
- ; COMM_FLAG 0-comm1 1-comm2 2-comm3 3-comm4
- ; Output - Serial port initialize for interrupt driven I/O
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- INIT_SERIAL PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH DX ;Save registers
- PUSH CX
- PUSH BX
- PUSH AX
- ;
- ; disable the interrupts on the 8250 and initialize DTR and RTS
- ;
- CLI ;Disable interrupts
- MOV DX,COMM_PORT ;Get UART base address
- ADD DX,4 ;Modem control register
- MOV AL,00001011B ;Set DTR, RTS, and OUT2
- OUT DX,AL
- ;
- ; set the baud rate of the UART and initialize line control register
- ;
- CMP BYTE PTR CONNECT_FLAG,0 ;If connect then use current
- JZ IS_10
- MOV AL,BYTE PTR CURRENT_SPEED
- JMP IS_20
- IS_10:
- MOV AL,SPEED_FLAG ;Get speed flag
- IS_20:
- MOV BYTE PTR CURRENT_SPEED,AL ;Save the current speed
- MOV BYTE PTR SPEED_COUNT,19
- CALL SET_BAUD_RATE
- ;
- ; set 8259 mask to enable the comm port interrupt
- ;
- MOV CL,BYTE PTR SET_VEC ;Get the interrupt number
- SUB CL,8 ; and adjust
- MOV AH,1 ;Mask for the interrupt
- SHL AH,CL
- NOT AH ;Invert
- IN AL,21H ;Get current 8259 int mask
- AND AL,AH ;Mask appropriate int bit
- OUT 21H,AL ;And set new 8259 mask
- ;
- ; enable the data received interrupt and reset the 8250
- ;
- SUB DX,3 ;Point to int enable reg
- MOV AL,3 ;Enable data received
- OUT DX,AL ; and transmit empty int
- DEC DX ;Point to base address
- MOV CX,7 ;Reset the serial port
- IS_30:
- IN AL,DX ;Read registers to reset
- INC DX
- LOOP IS_30
-
- CMP BYTE PTR COMM_INT_STA,0 ;Transmit int. running?
- JZ IS_50 ; no, so exit
- MOV AX,OUT_BUFF_HEAD ;Is data in output buffer
- CMP AX,OUT_BUFF_TAIL
- JZ IS_50 ;No, so exit
- MOV DX,COMM_PORT ;Get port base address
- ADD DX,5 ;Line status register
- IS_40:
- IN AL,DX ;Make sure holding reg. empty
- TEST AL,00100000B ;Test the hold reg empty flag
- JZ IS_40 ;Loop if not empty
- SUB DX,5 ;Port base register
- MOV AH,1 ;Use the output buffer
- CALL GET_BUFF_DATA ;Get data from output buffer
- OUT DX,AL ;Send the data out the port
- IS_50:
- STI ;Enable interrupts
- POP AX ;Restore registers
- POP BX
- POP CX
- POP DX
- RET
- INIT_SERIAL ENDP
-
- ;======================================================================
- ; Initialize routines. The initialize routine for unattended is first
- ; because it must remain resident.
- ;======================================================================
-
- ;-----------------------------------------------------------------------------
- ; Initialize the unattended program.
- ;-----------------------------------------------------------------------------
- INIT_UNATTENDED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
- CALL IU_10 ;Init pointers,clear video copy
- CALL MODIFY_INT8 ;Change INT 8 vector
- CALL MODIFY_INT21 ;Change INT 21 vector
- ;
- ; Terminate-Stay-Resident
- ;
- MOV DX,VIDEO_COPY ;Start of video copy
- ADD DX,4000D ;Allow room for video copy
- INT 27H ;Terminate-Stay-Resident
- ;
- ; Initialize buffer pointers and video copy pointer
- ;
- IU_10:
- PUSH ES ;Save extra segment
- MOV CX,OFFSET INITIALIZE ;CX points to begin of buffer
- ADD CX,256D ;Leave room for TSR stack
- CALL INIT_BUFFERS ;Initalize the buffer pointers
- INC CX ;Point to copy of video ram
- MOV TEMP_VIDEO_PTR,CX ;Save address of temp video buf
- ADD CX,BLOCK_SIZEX2 ;Save room for temp video data
- MOV VIDEO_COPY,CX ;Save address of video copy
- ;
- ; fill video RAM image with with space code since screen
- ; of manned system is blanked when connected
- ;
- PUSH CS ;Video copy is destination
- POP ES ;ES:DI points to video copy
- MOV DI,WORD PTR VIDEO_COPY
- MOV AX,0720H ;Data to fill buffer
- CLD ;Move upward
- MOV CX,2000D ;Move 2000 words
- REP STOSW ;Fill to force screen dump
- MOV CURSOR_POSITION,0FFFFH ;Force cursor position update
- MOV AL,1 ;Use setup string 2
- MOV BYTE PTR BAD_PASSWORD,0D ;Do not send exit code
- CALL RESET_MODEM ;Reset the modem
- POP ES ;Restore extra segment
- RET
- INIT_UNATTENDED ENDP
-
- ;-----------------------------------------------------------------------------
- ; INITIALIZE - Initialize the program. Determine whether it is manned
- ; or unattended by processing the command line. Initialize the serial
- ; port. This area is overwritten by PCREMOTE host mode to conserve memory.
- ;-----------------------------------------------------------------------------
- INITIALIZE PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- ;
- ; Display copyright notice.
- ;
- MOV DX,OFFSET COPYRIGHT ;Display copyright notice
- MOV AH,9 ;Display string
- INT 21H
- ;
- ; check to see if the program is already in memory
- ;
- MOV BYTE PTR START,0 ;Zero word to avoid false match
- XOR BX,BX ;Initialize search segment
- MOV AX,CS ;Save current segment in AX
- CLD ;Clear direction flag
- I_10:
- INC BX ;Increment search segment
- CMP AX,BX ;Reached current segment?
- JE I_20 ;Yes, PCREMOTE not resident
- MOV ES,BX ;Point ES to search segment
- MOV SI,OFFSET START ;Start of compare area
- MOV DI,SI ;Make offsets equal
- MOV CX,16D ;Check 16 characters
- REPE CMPSB ;Compare the strings
- JNE I_10 ;Compare failed
- MOV INSTALLED_SEG,BX ;Save the segment of resident
-
- ; MOV AH,09H ;Print string
- ; MOV DX,OFFSET PROG_RES ;Display program resident mess.
- ; INT 21H
- ; INT 20H ;Terminate
-
- ;
- ; Process command line for switches.
- ;
- I_20:
- PUSH CS ;Restore ES
- POP ES
- MOV BX,80H ;Point to command line length
- MOV AH,[BX] ;Get command line length
- I_30:
- OR AH,AH ;Check for commands
- JNZ I_40
- JMP I_210 ;None, so don't look
- I_40:
- INC BX ;Point to next data
- MOV AL,[BX] ;Get data
- DEC AH ;Decrement counter
- I_50:
- CMP AL,"?" ;Check for help menu (usage)
- JNE I_60 ;No, check for slash
- JMP HELP ;Yes, help is requested !
- I_60:
- CMP AL,"/" ;Check for slash
- JNE I_30 ;No, jump to check next data
- OR AH,AH ;Check for data after slash
- JNZ I_70
- JMP I_210 ;No, so don't process
- I_70:
- INC BX ;Point to next data
- MOV AL,[BX] ;Get data
- DEC AH ;Decrement counter
- CMP AL,"?" ;Check for help after a slash
- JNE I_80 ;No, check for comm2
- JMP HELP ;Yes, help is requested !
- I_80:
- CMP AL,"1" ;Check for comm1
- JNE I_90 ;No, check for another switch
- MOV BYTE PTR COMM_FLAG,0 ;Set comm1 flag
- I_90:
- CMP AL,"2" ;Check for comm2
- JNE I_100 ;No, check for another switch
- MOV BYTE PTR COMM_FLAG,1 ;Set comm2 flag
- I_100:
- CMP AL,"3" ;Check for comm port 3
- JNE I_110 ;No, jump to check next data
- MOV BYTE PTR COMM_FLAG,2 ;Set comm3 flag
- I_110:
- CMP AL,"4" ;Check for comm port 4
- JNE I_120 ;No, jump to check next data
- MOV BYTE PTR COMM_FLAG,3 ;Set comm4 flag
- JMP I_30 ;Process next switch
- I_120:
- OR AL,20H ;Force data to lower case
- CMP AL,"m" ;Check for manned switch
- JNE I_130 ;No, check for another switch
- INC BYTE PTR MANNED_FLAG ;Set manned flag
- JMP I_30 ;Process next switch
- I_130:
- CMP AL,"b" ;Check for baud rate
- JNE I_170 ;No, check for another switch
- OR AH,AH ;Check for data after slash
- JZ I_210 ;No, so don't process
- INC BX ;Point to next data
- MOV AL,[BX] ;Get data
- DEC AH ;Decrement counter
- CMP AL,"1" ;Check for 1200 baud
- JNE I_140
- MOV BYTE PTR SPEED_FLAG,0 ;1200 baud
- MOV AL,[BX+1] ;Check for 19200 baud
- CMP AL,"9"
- JNE I_140 ;No so continue
- INC BX ;Skip this data now
- DEC AH ;Decrement counter
- MOV BYTE PTR SPEED_FLAG,4 ;19200 baud
- JMP I_30
- I_140:
- CMP AL,"2" ;Check for 2400
- JNE I_150
- MOV BYTE PTR SPEED_FLAG,1 ;2400 baud
- I_150:
- CMP AL,"4" ;Check for 4800
- JNE I_160
- MOV BYTE PTR SPEED_FLAG,2 ;4800 baud
- I_160:
- CMP AL,"9" ;Check for 9600
- JNE I_165 ;Check next speed
- MOV BYTE PTR SPEED_FLAG,3 ;9600
- JMP I_30 ;Process next switch
- I_165:
- CMP AL,"3" ;Check for 38400
- JE I_166
- JMP I_50 ;maybe char is next slash
- I_166:
- MOV BYTE PTR SPEED_FLAG,5 ;38400
- JMP I_30 ;Process next switch
- I_170:
- CMP AL,"d" ;Check for desnow
- JNE I_180 ;No, process next switch
- INC BYTE PTR DESNOW_FLAG ;Set desnow flag
- JMP I_30 ;Process next switch
- I_180:
- CMP AL,"n" ;Check for null modem
- JNE I_190 ;No, process next switch
- INC BYTE PTR NULL_MODEM ;Set null modem flag
- JMP I_30 ;Process next switch
- I_190:
- CMP AL,"s" ;Check for smile face flag
- JNE I_200 ;No, process next switch
- INC BYTE PTR SMILE_FLAG ;Yes, set smile flag
- JMP I_30 ;No, check for more switches
- I_200:
- CMP AL,"u" ;Check for uninstall flag
- JNE I_205 ;No, process next switch
- JMP UNINSTALL ;If pcremote resident
- I_205:
- JMP I_30 ;Process next switch
-
- I_210:
- ;
- ; If PCREMOTE is resident and this is host mode then terminate
- ;
- CMP INSTALLED_SEG,0 ;Check for resident segment
- JZ I_215 ;none, then ok to continue
- CMP MANNED_FLAG,1 ;Check for manned mode
- JZ I_215 ;yes, then continue
- MOV AH,09H ;Print string
- MOV DX,OFFSET PROG_RES ;Display program resident mess.
- INT 21H
- INT 20H ;Terminate
- ;----------------------------------------------------------------------
- ; Initialize the serial port
- ;----------------------------------------------------------------------
- I_215:
- ;
- ; get the comm port base address using 2* comm port flag as offset
- ;
- PUSH DS ;Save data segment
- XOR BX,BX ;Zero BX
- MOV BL,COMM_FLAG ;Get comm port flag
- MOV SI,BX ;Save in index register
- SHL SI,1 ;Multiply by 2, word address
- MOV AX,40H ;Point DS to BIOS data area
- MOV DS,AX
- XOR BX,BX ;Point to comm port address
- MOV AX,[BX+SI] ;Get comm port address
- POP DS ;Restore data segment
- CMP AX,0 ;Make sure there is a entry
- JNZ I_230
- CMP BYTE PTR COMM_FLAG,2 ;Is this comm 3?
- JNZ I_220 ;No, must be comm4
- MOV AX,WORD PTR COMM_PORT3 ;Yes, get the comm port 3 add
- JMP I_230
- I_220:
- MOV AX,WORD PTR COMM_PORT4
- I_230:
- MOV WORD PTR COMM_PORT,AX ;Save comm port address
- ;
- ; modify the interrupt vector for the comm port
- ;
- CMP BYTE PTR COMM_FLAG,0 ;Determine INT vector to change
- JNZ I_240
- MOV AL,4 ;Comm 1 interrupt 4
- I_240:
- CMP BYTE PTR COMM_FLAG,1
- JNZ I_250
- MOV AL,3 ;Comm 2 interrupt 3
- I_250:
- CMP BYTE PTR COMM_FLAG,2
- JNZ I_260
- MOV AL,BYTE PTR COMM3_INT ;Comm 3 interrupt
- I_260:
- CMP BYTE PTR COMM_FLAG,3
- JNZ I_270
- MOV AL,BYTE PTR COMM4_INT ;Comm 4 interrupt
- I_270:
- ADD AL,8 ;Interrupt number
- CLI
- MOV BYTE PTR SET_VEC,AL ;
- CALL MODIFY_INTCOMM ;Change comm interrupt vector
- CALL INIT_SERIAL ;Initialize the serial port
- ;
- ; determine color or monochrome and save appropriate video segment
- ;
- MOV AH,0FH ;Determine video mode
- INT 10H ;By using BIOS int 10
- CMP AL,7 ;Check for monochrome
- JZ MONOCHROME ;Jump if it is
- MOV WORD PTR VIDEO_SEGMENT,0B800H ;Nope, it's CGA or EGA
- JMP I_280 ;Skip over
- MONOCHROME:
- MOV WORD PTR VIDEO_SEGMENT,0B000H ;It's a monochrome
- I_280:
- ;
- ; If manned then execute manned initialization, otherwise execute
- ; unattended initialization.
- ;
- CMP BYTE PTR MANNED_FLAG,0 ;Manned or unattended
- JZ I_290
- JMP INIT_MANNED ;Init the manned routines
- I_290:
- JMP INIT_UNATTENDED ;Init the unattended routines
- INITIALIZE ENDP
-
- ;----------------------------------------------------------------------
- ; Uninstall the resident (host) portion of PCREMOTE. Make sure another
- ; program did not change any of the interrupt vectors, if so, then the
- ; vectors cannot be restored properly and the program cannot be uninstalled.
- ; Tom - if this looks like some of your code, it is, I borrowed from
- ; PRN2FILE.
- ;----------------------------------------------------------------------
- UNINSTALL PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AL,08H ;Check the timer interrupt
- CALL CHECK_SEG
- JNE CANT_UNINSTALL ;If changed, can't uninstall
- MOV AL,21H ;Check DOS interrupt vector
- CALL CHECK_SEG
- JNE CANT_UNINSTALL ;If changed, can't uninstall
- MOV ES,INSTALLED_SEG ;Get the segment of resident
- MOV AL,BYTE PTR ES:SET_VEC ;Check comm interrupt vector
- CALL CHECK_SEG
- JNE CANT_UNINSTALL ;If changed, can't uninstall
- MOV ES,INSTALLED_SEG
- ASSUME DS:NOTHING, ES:NOTHING
- LDS DX,DWORD PTR ES:OLDINT_8;Get original timer vector
- MOV AX,2508H ;and change it back
- INT 21H
- LDS DX,DWORD PTR ES:OLDINT_21;Get original DOS vector
- MOV AX,2521H ;and change it back
- INT 21H
- ; comm vector changed last so PCREMOTE doesn't go to sleep
- CALL RESET_COMM ;Reset the comm port 8250
- LDS DX,DWORD PTR ES:OLDINT_COMM ;Get original comm vector
- MOV AX,ES:SET_VEC ;and change it back
- INT 21H
- ; release the memory allocated to the resident portion of PCREMOTE
- MOV ES,WORD PTR ES:2CH ;Get the environment segment
- MOV AH,49H ;Free allocated memory
- INT 21H
- JC RELEASE_ERR
- MOV ES,INSTALLED_SEG ;Resident program segment
- NOT WORD PTR ES:START ;Modify so can't find again
- MOV AH,49H ;Free allocated memory
- INT 21H
- JC RELEASE_ERR ;Error releasing the memory
- MOV DX,OFFSET YES_UNINSTALL ;Display uninstalled mess
- JMP UNI_10
- CANT_UNINSTALL:
- MOV DX,OFFSET NO_UNINSTALL ;Display can't uninstall mess
- JMP UNI_10
- RELEASE_ERR:
- MOV DX,OFFSET CANT_RELEASE ;Display can't release mess
- JMP UNI_10
- UNI_10:
- PUSH CS ;Restore the data segment
- POP DS
- MOV AH,09H ;Print string
- INT 21H
- MOV AX,4C00H
- INT 21H ;Terminate
- UNINSTALL ENDP
-
- ;----------------------------------------------------------------------
- ; Check to see if an interrupt vector points to the installed program
- ; segment.
- ; Input: AL contains interrupt to check.
- ; Output: Zero flag = 1 if yes, else Zero flag = 0
- ; Destroys: AH, ES
- ;----------------------------------------------------------------------
- CHECK_SEG PROC NEAR
- MOV AH,35H ;Get vector
- INT 21H
- MOV AX,ES ;Save returned segment
- CMP AX,INSTALLED_SEG ;Is it installed segment
- RET
- CHECK_SEG ENDP
-
- ;----------------------------------------------------------------------
- ; Initialize the manned program. Initialize buffers, and change INT 8
- ; vector.
- ;----------------------------------------------------------------------
- INIT_MANNED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- CALL GET_COMSPEC
- MOV CX,OFFSET LAST_BYTE ;CX points to begin of buffer
- CALL INIT_BUFFERS ;Initalize the buffer pointers
- MOV AX,VIDEO_SEGMENT ;Set ES to point to video RAM
- MOV ES,AX
- JMP CONNECT_MANNED ;Run manned portion of program
- INIT_MANNED ENDP
-
- ;======================================================================
- ; Data used by manned portion of program only. Not required to be
- ; resident for unattended mode.
- ;======================================================================
- HOST_PORT EQU BYTE PTR CONNECT_UNATTENDED ;Host port number (1-4) DB
- OLD_CURSOR EQU WORD PTR HOST_PORT+1 ;Cursor position save field DW
- UP_LENGTH EQU WORD PTR OLD_CURSOR+2 ;Upload string length DW
- DN_LENGTH EQU WORD PTR UP_LENGTH+2 ;Download string length DW
- PATH_LENGTH EQU WORD PTR DN_LENGTH+2 ;Pathname string length DW
- LAST_KEY EQU BYTE PTR PATH_LENGTH+2 ;Last key pressed save field DB
- EXEC_VAL EQU BYTE PTR LAST_KEY+1 ;Shell Variable (1-3) DB
- ; 1 = Remote shell to DOS
- ; 2 = Remote Download
- ; 3 = Remote Upload
- UPDN_STRING EQU BYTE PTR EXEC_VAL+1 ;Upload string (filename)
- PATH_STRING EQU BYTE PTR UPDN_STRING+44 ;Path string (drive & path)
- ORGDSK EQU BYTE PTR PATH_STRING+44 ;1 byte
- ORGPTH EQU BYTE PTR ORGDSK+1 ;256 bytes
- BLOCK_DATA_COUNT DB 0 ;Number of bytes left to rec.
- TYPE_TRANSFER DB 0FFH ;FF - No data transfer in prog.
- ;00 - Received char. data
- ;01 - Received attr. data
- RPT_STATUS DB 0 ;00 - No data repeat
- ;02 - Repeat the char in block
- CUR_STATUS DB 0 ;0=No cursor data being rec.
- ; otherwise, byte count
- CUR_LOW DB 0 ;Low byte of cursor data
- CUR_HIGH DB 0 ;High byte of cursor data
- ENTER_NUMBER DB CR,LF,CR,LF,"Enter phone number:$"
- NO_CARRIER DB CR,LF,"No carrier.$"
- MODEM_ERROR DB CR,LF,"Error.$"
- TERMINATE_MESS DB CR,LF,"Returning to DOS.$"
- PROG_RES DB CR,LF,"PCREMOT2 is already resident.$"
- NO_UNINSTALL DB CR,LF,"Cannot uninstall PCREMOT2.$"
- YES_UNINSTALL DB CR,LF,"PCREMOT2 uninstalled successfully.$"
- CANT_RELEASE DB CR,LF,"Error release PCREMOT2 resident memory.$"
- SHELL_PROMPT DB " Shell to DOS initiated. Type 'EXIT' at any DOS "
- DB "prompt to return to PCREMOT2. ",0
- TRANSFER_PROMPT DB " File transfer initiated ... ",0
- PARM_$_1200 DB "/a /8 /r",0 ;ZCOPY parm 1200 baud
- PARM_$_2400 DB "/a /7 /r",0 ;ZCOPY parm 2400 baud
- PARM_$_4800 DB "/a /6 /r",0 ;ZCOPY parm 4800 baud
- PARM_$_9600 DB "/a /5 /r",0 ;ZCOPY parm 9600 baud
- PARM_$_19200 DB "/a /4 /r",0 ;ZCOPY parm 19200 baud
- PARM_$_38400 DB "/a /3 /r",0 ;ZCOPY parm 38400 baud
- PARM_STRING DB " ",0 ;Actual ZCOPY parm
- ASCII_CODE DB "~`!1@2#3$4%5^6&7*8(9)0_-+|\=QWERTYUIOP{[}]ASDFGHJKL:;"
- DB 34D,39D,CR,"ZXCVBNM<,>.?/ "
- SCAN_CODE DB 1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12
- DB 13,13,14,14,17,18,19,20,21,22,23,24,25,26,27,27,28,28
- DB 31,32,33,34,35,36,37,38,39,40,40,41,41,43,46,47,48,49
- DB 50,51,52,53,53,54,54,55,55,61
- ZCOPY DB "ZCOPY ",0 ;ZCOPY command line
- REMOTE_COM DB "COM ",0 ;Remote Comm value
- HOST_COM DB "COM ",0 ;Host Comm value
- UPDNLOAD_COM DB " /c zcopy ", 90 DUP(?)
- HELP_SCREEN DB CR,LF
- DB " Usage : PCREMOT2 [ /# ] [ /B# ] [ /M ] [ /D ] [ /S ] [ /N ]"
- DB CR,LF,CR,LF
- DB " [ /# ] - # = Communication port number ( 1 - 4 ) "
- DB CR,LF
- DB " [ /B# ] - # = Baud rate 1=1200, 2=2400, 4=4800, 9=9600 "
- DB CR,LF
- DB " null modem only 19=19200, 3=38400 "
- DB CR,LF
- DB " [ /M ] - Manned mode (used on remote computer) "
- DB CR,LF
- DB " [ /D ] - Desnow flag (used on CGA monitors) "
- DB CR,LF
- DB " [ /S ] - Smile face enable (used on host computer) "
- DB CR,LF
- DB " [ /N ] - Null modem connects the two computers "
- DB CR,LF
- DB " [ /U ] - Uninstall (used on host computer to remove from memory) "
- DB CR,LF,CR,LF,"$",26
- EXIT_MESSAGE DB " "
- DB " ┌──────────────────┐ "
- DB " │ OK to EXIT? (Y/N)│ "
- DB " └──────────────────┘ "
- DB " "
- BOX_CHAR DW 164 ;location for character
- DB '╔' ;Character for box
- DW 256
- DB '╗'
- DW 324
- DB '║'
- DW 416
- DB '║'
- DW 484
- DB '╠'
- DW 576
- DB '╣'
- DW 644
- DB '║'
- DW 804
- DB '║'
- DW 964
- DB '║'
- DW 1124
- DB '║'
- DW 736
- DB '║'
- DW 896
- DB '║'
- DW 1056
- DB '║'
- DW 1216
- DB '║'
- DW 1284
- DB '╠'
- DW 1376
- DB '╣'
- DW 1444
- DB '║'
- DW 1536
- DB '║'
- DW 1604
- DB '╚'
- DW 1696
- DB '╝'
- TRANSFER_MESS DB "FILE TRANSFER REQUESTED",0
- DB " ",0
- DB " (U)pload - Send file(s) to Host System.",0
- DB " or",0
- DB " (D)ownload - Receive file(s) from Host.",0
- UPLOAD_MESS DB " UPLOAD REQUESTED",0
- DB "Enter the full pathname of the file(s) on ",0
- DB "the remote system which you want to upload",0
- DB "to the host system.",0
- DB ":",0
- DOWNLOAD_MESS DB " DOWNLOAD REQUESTED",0
- DB "Enter the full pathname of the file(s) on ",0
- DB "the host system which you want to download",0
- DB "to the remote system.",0
- DB ":",0
- UP_PATH_MESS DB " UPLOAD REQUESTED",0
- DB "Enter the path on the host system to place ",0
- DB "the uploaded file(s). No target, other",0
- DB "than directory path, may be specified.",0
- DB ":",0
- DN_PATH_MESS DB " DOWNLOAD REQUESTED",0
- DB "Enter the path on the remote system to place",0
- DB "the downloaded file(s). No target, other",0
- DB "than directory path, may be specified.",0
- DB ":",0
- PRESS_ESC DB "Press <ESC> to return to PCREMOT2",0
- ;
- ;-----------------------------------------------------------------------
- ;
- COMSPC LABEL DWORD
- COM_OFS DW 0000
- COM_SEG DW 0000
-
- PAR_BLK DW 0000
- DW 0000 ; OFFSET NUL_TAIL
- DW 0000
- DW 0000
- DD 0FFFFH
- NOEXEC DB 00
- ;--------------------------------------------------------------------
- ;
- COM_VAR DB 'COMSPEC='
- NUL_TAIL DB 00
- ;
- ; DON'T REMOVE OR PHYSICALLY REARRANGE THIS
- ;
- GODPMT DB '$P$G',00
- PMTSTR DB 'PROMPT=',00
- PMTLOC DW 0000
- DFTPMT DB 'PROMPT='
- PCRSTR DB 'DOS SHELL- '
- PMTLGT DW $-OFFSET PCRSTR
-
- ;======================================================================
- ; The manned routine will execute the connect manned routine to call the
- ; unattended system. These routines are only used in the manned mode.
- ;======================================================================
-
- ;----------------------------------------------------------------------
- ; User requested a help screen by including a question mark in the
- ; command line. Therefore, display the usage for PCREMOTE and end
- ; the program.
- ;----------------------------------------------------------------------
- HELP PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH CS ;
- POP DS ;DS->CS
- MOV AH,09H ;String print INT21 (09)
- MOV DX,OFFSET HELP_SCREEN ;DS:DX->Help screen variable
- INT 21H ;Display the help screen
- INT 20H ;Terminate the program
- HELP ENDP
-
- ;----------------------------------------------------------------------
- ; Connect manned asks for the phone number to call, dials the number
- ; and waits for connect. Once connected it sends bursts of 20 CRs at
- ; one second intervals. When it receives alpha data it processes video
- ; data and waits for sync byte (00), then transfers control to the
- ; manned routine.
- ;----------------------------------------------------------------------
- CONNECT_MANNED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH ES ;
- PUSH CS ;
- POP ES ;
- MOV BX,1000H ;
- MOV AH,4AH ;
- INT 21H ;
- POP ES ;
- CM_10:
- CMP BYTE PTR NULL_MODEM,0 ;If null modem skip number
- JNZ CM_50
- XOR AL,AL ;Use setup string 1
- CALL RESET_MODEM ;Reset the modem first
- MOV DX,OFFSET ENTER_NUMBER ;Point to enter number mess.
- MOV AH,9 ;Display message
- INT 21H
- MOV DX,OFFSET UPDN_STRING ;Unused area as keyboard buffer
- MOV BX,DX ;Enter max characters for input
- MOV BYTE PTR [BX],40D
- MOV AH,0AH ;Buffered keyboard input
- INT 21H ;Get the phone number
- MOV AL,1 ;Wait a second
- CALL DELAY
- MOV SI,OFFSET UPDN_STRING ;Point to phone number
- INC SI ;Amount of data in key buffer
- XOR AX,AX ;Zero AX
- CLD ;Forward
- LODSB ;Get count
- OR AL,AL ;Check for no input
- JNZ CM_20 ;If there is then continue
- JMP EXIT_MANNED ;No, then exit program
- CM_20:
- PUSH SI ;Save pointer
- MOV SI,OFFSET TONE_DIAL ;Send the tone dial command
- CALL LOAD_ZSTRING
- POP SI ;Restore pointer
- ADD SI,AX ;Point to end of buffer
- INC SI ;Include CR code
- MOV BYTE PTR [SI],0 ;And put a zero on end
- DEC SI ;Adjust for previous INC
- SUB SI,AX ;Back to begin of buffer
- CALL LOAD_ZSTRING ;Dial the phone number
- MOV AL,1 ;Wait a second
- CALL DELAY
- CALL CLEAR_INBUFF ;Clear input buffer
- CM_30:
- CALL GET_KEYSTROKE ;Check for a keystroke
- JZ CM_40 ;None, so wait
- CMP AL,ESC_KEY ;Check for ESCAPE
- JNZ CM_40 ;No
- JMP CM_10 ;Yes, then enter new number
- CM_40:
- CALL CHECK_CARRIER ;Check for a connect signal
- JZ CM_60 ;No, then check for err codes
- CM_50:
- CALL CLEAR_SCREEN ;Yes, blank the screen
- MOV BYTE PTR CONNECT_FLAG,1 ;Set the connect flag
- JMP CM_90 ;Execute manned
- CM_60:
- MOV AH,0 ;Use input buffer
- CALL GET_BUFF_DATA ;Get data from buffer
- JNC CM_30 ;No data, try again
- CMP AL,"3" ;No carrier code?
- JNZ CM_80 ;No, check for other code
- CM_70:
- MOV DX,OFFSET NO_CARRIER ;Send no carrier message
- MOV AH,09H
- INT 21H
- JMP CM_10 ;Yes, reset modem and try again
- CM_80:
- CMP AL,"8" ;2400 no answer code
- JZ CM_70 ;Yes, display no carrier mess
- CMP AL,"4" ;Error code?
- JNZ CM_30 ;No, check for other code
- MOV DX,OFFSET MODEM_ERROR ;Send modem command error mess
- MOV AH,09H
- INT 21H
- JMP CM_10 ;Yes, reset modem and try again
- CM_90:
- MOV AL,1 ;Wait for a second
- CALL DELAY
- MOV BYTE PTR CR_COUNT,30D ;Send 30 CRs at a time
- CM_100:
- CALL CHECK_CARRIER ;Check for carrier loss
- JNZ CM_110 ;No, then continue
- JMP EXIT_MANNED ;Yes, then exit
- CM_110:
- CALL GET_KEYSTROKE ;Check for a keystroke
- JZ CM_120 ;None, so wait
- CMP AL,ESC_KEY ;Check for ESCAPE
- JNZ CM_120 ;No
- JMP EXIT_MANNED ;Yes, give up
- CM_120:
- MOV AX,OUT_BUFF_TAIL ;Is output buffer empty?
- CMP AX,OUT_BUFF_HEAD
- JNZ CM_130 ;No, skip CR
- MOV AL,CR ;Send a CR for speed sync
- MOV AH,1 ;Use output buffer
- CALL PUT_BUFF_DATA
- DEC BYTE PTR CR_COUNT ;Decrement CR counter
- JZ CM_90
- CM_130:
- MOV AH,0 ;Use input buffer
- CALL GET_BUFF_DATA ; and check for data
- JNC CM_100 ;No data so keep checking
- CMP AL,'@' ;Alpha message?
- JL CM_100 ;No, then wait for it
- CM_140:
- CMP BYTE PTR NULL_MODEM,0 ;Using a null modem ?
- JZ CM_150 ;No... no need for exit check
- PUSH AX ;Store AX just in case
- MOV AH,AL ;Set up AX for exit compare
- XOR AL,AL ;Reset AL to zero
- CMP WORD PTR EXIT_CODE,AX ;Did host send exit_code ?
- POP AX ;Restore AX just in case no
- JNZ CM_150 ;No check for sync byte
- JMP EXIT_MANNED ;Yes, exit back to DOS
- CM_150:
- CMP AL,0 ;Is data a sync byte
- JNE CM_270 ;No, then put data on screen
- CM_160: ;
- MOV AH,0 ;Input buffer
- CALL GET_BUFF_DATA ;Receive a character
- JNC CM_160 ;Did we receive one yet ?
- CMP AL,0 ;Sync byte ?
- JE CM_160 ;Yes
- ;
- ; A character was received that is not a sync byte. This is the host trying
- ; to tell the remote computer what Comm port the host is currently running
- ; through. Because garbage (line noise) is always a threat, remote must
- ; accurately determine which Comm port was sent.
- ;
- PUSH CX ;Store register
- PUSH DX ;Store register
- XOR CX,CX ;Reset counters to zero
- XOR DX,DX ;Reset counters to zero
- JMP CM_180 ;Process AL data
- CM_170:
- MOV AH,0 ;Use input buffer
- CALL GET_BUFF_DATA ;Receive a character
- JNC CM_170 ;Did we get one yet ?
- CMP AL,0 ;Sync byte ?
- JE CM_220 ;Yes, determine host comm
- CM_180:
- CMP AL,1D ;One received ?
- JNE CM_190 ;No
- INC CL ;Yes, bump Comm 1 counter
- CM_190:
- CMP AL,2D ;Two received ?
- JNE CM_200 ;No
- INC CH ;Yes, bump Comm 2 counter
- CM_200:
- CMP AL,3D ;Three received ?
- JNE CM_210 ;No
- INC DL ;Yes, bump Comm 3 counter
- CM_210:
- CMP AL,4D ;Four received ?
- JNE CM_170 ;No, get another character
- INC DH ;Yes, bump Comm 4 counter
- JMP CM_170 ;Get another character
- CM_220:
- MOV AL,'1' ;Assume Comm 1 for now
- CMP CH,CL ;Comm2 count > Comm1 count ?
- JLE CM_230 ;No
- MOV AL,'2' ;Yes, assume Comm2 for now
- MOV CL,CH ;Save Comm2 counter in CL
- CM_230:
- CMP DL,CL ;Comm3 count > CL (current)
- JLE CM_240 ;No
- MOV AL,'3' ;Yes, assume Comm3 for now
- MOV CL,DL ;Save Comm3 counter in CL
- CM_240:
- CMP DH,CL ;Comm4 count > CL (current)
- JLE CM_250 ;No
- MOV AL,'4' ;Yes, Host port = Comm4
- CM_250:
- MOV HOST_PORT,AL ;Save largest port counter
- POP DX ;Restore register
- POP CX ;Restore register
- CALL MAKE_PARM_STRING ;Make ZCOPY parm w/ baud & comm
- CM_260:
- CALL GET_BUFF_DATA ;Receive a character
- JNC CM_260 ;Did we receive one yet ?
- CMP AL,0 ;Sync Byte ?
- JNE CM_270 ;Yes
- CALL CLEAR_SCREEN ;Blank the screen
- JMP MANNED ;We're in, let's run program
- CM_270:
- MOV DL,AL ;Prepare to display character
- MOV AH,2 ; using DOS
- INT 21H ;Display it
- CM_280:
- CALL CHECK_CARRIER ;Check for carrier loss
- JNZ CM_290 ;No, then continue
- JMP EXIT_MANNED ;Yes, then exit
- CM_290:
- CALL GET_KEYSTROKE ;Check for a keystroke
- JZ CM_310 ;If none, skip next routine
- ;
- ; Check for exit code, if it is then exit
- ;
- CMP AX,WORD PTR EXIT_CODE ;Check for exit code
- JNZ CM_300 ;No, so continue
- CALL CONFIRM_EXIT ;Yes, confirm exit
- JNZ CM_310 ;No, so continue, don't send
- JMP EXIT_MANNED ;Otherwise reset and exit
- CM_300:
- CALL SEND_KEYSTROKE ;Send to unattended system
- CM_310:
- MOV AH,0 ;Use input buffer
- CALL GET_BUFF_DATA ; and check for data
- JNC CM_280 ;No data, check for keys
- JMP CM_140 ;Check for sync byte
- CONNECT_MANNED ENDP
-
- ;----------------------------------------------------------------------
- ; MAKE_PARM_STRING creates the ZCOPY parameters using the current baud
- ; rate of the remote system. This PROC also creates REMOTE_COM using
- ; the COMM_FLAG. REMOTE_COM is used in MAKE_UP_COM & MAKE_DN_COM.
- ;----------------------------------------------------------------------
- MAKE_PARM_STRING PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Store registers & flags
- PUSH CX
- PUSH DS
- PUSH ES
- PUSH DI
- PUSH SI
- PUSHF
- CLD ;Direction flag -> forward
- PUSH CS
- PUSH CS
- POP DS ;DS->CS
- POP ES ;ES->CS
- MOV DI,OFFSET PARM_STRING ;DI->Parm string's first char
- MOV SI,OFFSET PARM_$_1200 ;SI->1st char of 1200 var.
- CMP BYTE PTR SPEED_FLAG,1D ;2400 Baud ?
- JNE MPS_10 ;Yes, use 2400 baud variable
- MOV SI,OFFSET PARM_$_2400 ;SI->1st char of 2400 var.
- MPS_10:
- CMP BYTE PTR SPEED_FLAG,2D ;4800 Baud ?
- JNE MPS_20 ;Yes, use 4800 baud variable
- MOV SI,OFFSET PARM_$_4800 ;SI->1st char of 4800 var.
- MPS_20:
- CMP BYTE PTR SPEED_FLAG,3D ;9600 Baud ?
- JNE MPS_30
- MOV SI,OFFSET PARM_$_9600 ;SI->1st char of 9600 var.
- MPS_30:
- CMP BYTE PTR SPEED_FLAG,4D ;19200 Baud ?
- JNE MPS_32
- MOV SI,OFFSET PARM_$_19200 ;SI->1st char of 19200 var.
- MPS_32:
- CMP BYTE PTR SPEED_FLAG,5D ;38400 Baud ?
- JNE MPS_34
- MOV SI,OFFSET PARM_$_38400 ;SI->1st char of 38400 var.
- MPS_34:
- MOV CX,8D ;Move 8 letters
- MPS_40:
- LODSB ;Pick off char. and place it
- STOSB ; in the real ZCOPY parm string
- LOOP MPS_40 ;11 characters done ?
- ;
- ; Remote comm must be set up using COMM_FLAG
- ;
- MOV DI,OFFSET REMOTE_COM ;ES:DI-> (C)om var. 1st char
- ADD DI,3D ;ES:DI-> COM( ) var. 4th char
- MOV AL,'1' ;Assume remote using com1
- CMP BYTE PTR COMM_FLAG,1D ;Using com2 ?
- JNE MPS_50 ;No
- MOV AL,'2' ;Remote using com2
- MPS_50:
- CMP BYTE PTR COMM_FLAG,2D ;Using com3 ?
- JNE MPS_60 ;No
- MOV AL,'3' ;Remote using com3
- MPS_60:
- CMP BYTE PTR COMM_FLAG,3D ;using com4?
- JNE MPS_70 ;No
- MOV AL,'4' ;Remote using com4
- MPS_70:
- STOSB ;Store com (1-4) variable
- ;
- ; HOST_COM must be set up using the HOST_PORT variable.
- ;
- MOV AL,HOST_PORT ;Ready AL for STOSB
- MOV DI,OFFSET HOST_COM ;ES:DI->1st char of HOST_COM
- ADD DI,3D ;ES:DI->4th char of HOST_COM
- STOSB ;Store HOST_COM into variable
- POPF ;Restore flags & registers
- POP SI
- POP DI
- POP ES
- POP DS
- POP CX
- POP AX
- RET
- MAKE_PARM_STRING ENDP
-
- ;----------------------------------------------------------------------
- ; Manned portion of the program. Not RAM resident. Sends keystrokes
- ; to the unattended computer. Data from unattended computer is
- ; decoded and processed.
- ;----------------------------------------------------------------------
- MANNED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- ;
- ; Check for loss of carrier
- ;
- CALL CHECK_CARRIER ;No, check for carrier loss
- JNZ M_10 ;No loss so continue
- JMP EXIT_MANNED ;Otherwise reset and exit
- ;
- ; Check to see if shift status has changed, if so, put new status
- ; in the output buffer
- ;
- M_10:
- MOV AH,2 ; Prepare shift status
- INT 16H ; Get shift status
- CMP SHIFT_STATUS,AL ; See if the same
- JE M_20 ; If so, next routine
- MOV SHIFT_STATUS,AL ; Save new status
- MOV AL,0FDH ; Sync, expect shift
- MOV AH,1 ; Put into out buff
- CALL PUT_BUFF_DATA ;
- MOV AL,SHIFT_STATUS ; Get shift status
- CALL PUT_BUFF_DATA ; Send to host system
- ;
- ; Check for keystoke, if so, put the ASCII code and scan code
- ; into the output buffer, check it for exit code
- ;
- M_20:
- CALL GET_KEYSTROKE ;Check for keystroke
- JNZ M_30
- JMP M_90 ;If none skip this routine
- ;
- ; Check for shell to DOS, if it is then shell & return
- ;
- M_30:
- CMP AX,WORD PTR SHELL_CODE ; Shell key pressed ?
- JNE M_40 ; No....
- MOV EXEC_VAL,1D ; Tell EXEC to shell
- CALL EXEC_ZCOPY ; EXEC to shell
- CALL INIT_SERIAL ; Re-initialize serial port
- CALL CLEAR_SCREEN ; Clear the remote screen
- MOV AX,WORD PTR CLEAR_CODE ; Send clear_code to
- CALL SEND_KEYSTROKE ; rewrite entire screen
- JMP M_90 ; Process next char
- ;
- ; Check for exit code, if it is then exit
- ;
- M_40:
- CMP AX,WORD PTR EXIT_CODE ;Check for exit code
- JNZ M_50 ;No, so continue
- PUSH DX ; Store DX
- CALL GET_CURSOR ; Get cursor pos.
- MOV OLD_CURSOR,DX ; Save Cursor pos.
- MOV DH,25D ; Place cursor
- MOV DL,79D ; off screen
- CALL PUT_CURSOR ; Set cursor pos.
- POP DX ; Restore DX
- CALL CONFIRM_EXIT ;Yes, confirm exit
- PUSH DX ; Store DX
- MOV DX,OLD_CURSOR ; Restore cursor pos.
- CALL PUT_CURSOR ; Set cursor pos.
- POP DX ; Restore DX
- JNZ M_90 ;No, so continue, don't send
- JMP EXIT_MANNED ;Otherwise reset and exit
- ;
- ; Check for transfer code, if it is then ask to upload or download
- ;
- M_50: ;
- CMP AX,WORD PTR TRANSFER_CODE ; Check for transfer
- JNZ M_70 ; No, so continue
- PUSH DX ; Store register
- CALL GET_CURSOR ; Get cursor position
- MOV OLD_CURSOR,DX ; Save cursor in old cursor
- MOV DH,25D ; Cursor Row = 25
- MOV DL,79D ; Cursor Col = 79
- CALL PUT_CURSOR ; Position Cursor
- POP DX ; Restore DX register
- CALL TRANSFER_TYPE ; Transfer file
- CMP AX,WORD PTR CLEAR_CODE ; Transferred files ?
- JNE M_60 ; Yes-reset remote scrn
- CALL INIT_SERIAL ; Re-initialize serial port
- CALL CLEAR_INBUFF
- CALL CLEAR_OUTBUFF
- JMP M_70 ; Send clear screen code
- M_60:
- PUSH DX ; Push DX register
- MOV DX,OLD_CURSOR ; Put cursor back
- CALL PUT_CURSOR ; where it was
- POP DX ; Restore DX register
- JMP M_90 ; Transfer complete
- ;
- ; Check for clear and resend entire screen code.
- ;
- M_70: ;
- CMP AX,WORD PTR CLEAR_CODE ; Clear screen pressed?
- JNZ M_80 ; No...
- PUSH AX ; Yes.... save key
- CALL CLEAR_SCREEN ; Clear remote screen
- POP AX ; Restore key
- M_80: ;
- CALL SEND_KEYSTROKE ; Send key to host
- ;
- ; Check for receive data, if available, get data and decode
- ;
- M_90:
- MOV AH,0 ;Get data from input buffer
- CALL GET_BUFF_DATA
- JC M_100 ;Data is there, so process
- JMP M_EXIT ;No data,so loop again
- M_100:
- CMP BYTE PTR TYPE_TRANSFER,0FFH ;Check transfer type
- JZ M_160 ;If ff, check for sync byte
- CMP VID_RAM_OFFSET,0FFFFH ;Received block no. yet?
- JNZ M_120 ;Yes, then process as data
- MOV BYTE PTR BLOCK_DATA_COUNT,BLOCK_SIZE ;Data counter
- MOV BX,BLOCK_SIZEX2 ;Get block size in bytes
- MUL BX ;Block number X block size
- ADD AL,TYPE_TRANSFER ;Adjust for char. or attr.
- MOV VID_RAM_OFFSET,AX ;Save pointer to video RAM
- JMP M_EXIT
- M_120:
- MOV DI,VID_RAM_OFFSET ;Point to video RAM
- CMP BYTE PTR RPT_STATUS,0 ;Check the repeat flag
- JZ M_140 ;Normal data transfer
- MOV CL,BYTE PTR BLOCK_DATA_COUNT ;Number to repeat
- XOR CH,CH
- M_130:
- CALL PUT_VIDEO_DATA ;Store the data in video RAM
- INC DI ;Point to next video RAM loc.
- LOOP M_130
- JMP M_150 ;End of data, reset variables
- M_140:
- CALL PUT_VIDEO_DATA ;Store the data in video RAM
- INC DI ;Point to next video RAM loc.
- MOV VID_RAM_OFFSET,DI ;And save pointer
- DEC BYTE PTR BLOCK_DATA_COUNT ;Dec. data counter
- JZ M_150 ;End of data, reset variables
- JMP M_EXIT ;Otherwise continue
- M_150:
- MOV BYTE PTR TYPE_TRANSFER,0FFH ;Reset type transfer flag
- JMP M_EXIT
- M_160:
- CMP BYTE PTR CUR_STATUS,0 ;Check cursor status
- JZ M_170 ;If 0, check for sync byte
- XOR BX,BX ;Zero BX for index
- MOV BL,BYTE PTR CUR_STATUS ;Use as index for cursor data
- MOV DI,OFFSET CUR_STATUS ;Base address for cursor data
- MOV [DI+BX],AL ;Save the register data
- INC BL ;Increment count
- MOV BYTE PTR CUR_STATUS,BL ;And save it
- CMP BL,3 ;Check to see if we have 3 byte
- JNZ M_EXIT ;No, so wait till enough data
- MOV BH,0 ;Always use page one
- MOV DX,WORD PTR CUR_LOW ;Get cursor position
- MOV AH,2 ;Set cursor function
- INT 10H
- MOV BYTE PTR CUR_STATUS,0 ;Reset cursor status
- JMP M_EXIT
- M_170:
- PUSH AX ;Save the data
- AND AL,0FCH ;Mask out data type and repeat
- CMP AL,0FCH ;Video data sync?
- JNZ M_180 ;No, check for cursor sync
- POP AX ;Restore data
- PUSH AX
- AND AL,1 ;Save data type
- MOV TYPE_TRANSFER,AL ;Set transfer type flag
- POP AX ;Restore data
- AND AL,2 ;Save repeat flag
- MOV RPT_STATUS,AL ;Set repeat flag
- MOV VID_RAM_OFFSET,0FFFFH ;Prepare to receive block no.
- JMP M_EXIT
- M_180:
- POP AX ;Restore data
- CMP AL,0D2H ;Check for cursor data sync
- JNZ M_EXIT ;If not, then throw away
- MOV BYTE PTR CUR_STATUS,1 ;Set cursor status byte
- M_EXIT:
- JMP MANNED ;Do it again
- MANNED ENDP
-
- ;----------------------------------------------------------------------
- ; Exit manned. The exit code is sent, interrupt vector reset, and
- ; the modem is hung up and reset
- ; Input - Nothing
- ; Output - DOS
- ; Changes - everything
- ;----------------------------------------------------------------------
- EXIT_MANNED PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AX,WORD PTR EXIT_CODE ;Get the exit code
- CALL SEND_KEYSTROKE ;Send the exit code
- CALL CLEAR_SCREEN ;Blank the screen
- MOV DX,OFFSET TERMINATE_MESS ;Display terminate call mess.
- MOV AH,09H
- INT 21H
- XOR AL,AL ;Reset modem and exit
- CALL RESET_MODEM
- MOV AL,1 ;Wait a second
- CALL DELAY
- CALL RESET_COMM
- LDS DX,DWORD PTR OLDINT_COMM ;Get original comm vector
- MOV AX,SET_VEC ;and change it back
- INT 21H
- INT 20H ;Terminate program
- EXIT_MANNED ENDP
-
- ;----------------------------------------------------------------------
- ; Reset comm port. Resets the comm port 8250 and disables interrupt
- ; driven I/O. Reset the 8259 mask.
- ;----------------------------------------------------------------------
- RESET_COMM PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH ES
- PUSH DS
- PUSH CS
- POP DS
- CMP INSTALLED_SEG,0 ;Maybe this is uninstall
- JZ EM_10
- MOV ES,INSTALLED_SEG ;Get location of resident prog
- MOV DX,ES:COMM_PORT ;Get the comm port it used
- MOV CL,BYTE PTR ES:SET_VEC ;Determine mask bit to change
- JMP EM_20
- EM_10:
- MOV DX,CS:COMM_PORT ;Get port address
- MOV CL,BYTE PTR SET_VEC ;Determine mask bit to change
- EM_20:
- INC DX ;Interrupt enable reg.
- XOR AL,AL
- OUT DX,AL ;Disable all interrupts
- SUB CL,8 ; and adjust
- MOV AH,1
- SHL AH,CL ;Select the mask bit to set
- IN AL,21H ;Get current 8259 int mask
- OR AL,AH ;Set appropriate int bit
- OUT 21H,AL ;And set new 8259 mask
- POP DS
- POP ES ;Restore segment
- RET
- RESET_COMM ENDP
-
- ;----------------------------------------------------------------------
- ; Clear screen. This routine will blank the video display
- ; Input - Nothing
- ; Output - Screen is cleared
- ; Changes - AX, BX, CX, DX
- ;----------------------------------------------------------------------
- CLEAR_SCREEN PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV BX,0 ;Use video page one
- MOV DX,0 ;Position cursor at row 0 col 0
- MOV AH,2 ;Set cursor function
- INT 10H
- MOV AX,0700H ;Scroll down, clear screen
- MOV BH,07H ;White on black
- MOV CX,0 ;Upper left corner
- MOV DH,24D ;Lower right corner
- MOV DL,79D
- INT 10H ;Video BIOS call
- RET
- CLEAR_SCREEN ENDP
-
- ;----------------------------------------------------------------------
- ; Display OK to exit message and wait for response
- ; Input - Nothing
- ; Output - Zero flag set - exit, zero flag reset - do not exit
- ; Changes - CX, SI, DI
- ;----------------------------------------------------------------------
- CONFIRM_EXIT PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save the exit code
- CE_10:
- MOV AX,OUT_BUFF_HEAD ;Wait until the out buffer
- CMP AX,OUT_BUFF_TAIL ; is empty
- JNZ CE_10
- ;
- ; Save the existing video data in the output buffer
- ;
- CALL SWITCH_DS_ES
- MOV DI,ES:OUT_BUFF_END ;Use output buffer as temp stor.
- MOV SI,0 ;Upper left corner of video
- MOV CX,5 ;Transfer 5 lines
- CE_20:
- PUSH CX ;Save line counter
- MOV CX,24D ;Transfer 24 char. per line
- REPNZ MOVSW
- ADD SI,112D ;Next line
- POP CX ;Restore line counter
- LOOP CE_20
- ;
- ; Display the ok to exit message
- ;
- CALL SWITCH_DS_ES
- MOV DI,0 ;Upper left corner of video
- MOV SI,OFFSET EXIT_MESSAGE ;Exit message
- MOV CX,5 ;Display 5 lines
- CE_30:
- PUSH CX ;Save line counter
- MOV CX,24D ;Display 20 characters per line
- CE_40:
- LODSB
- CALL PUT_VIDEO_DATA ;Display the character
- MOV AL,70H ;White on black attribute
- CALL PUT_VIDEO_DATA ;Store attribute
- LOOP CE_40
- ADD DI,112D ;Next line
- POP CX ;Restore line counter
- LOOP CE_30
- ;
- ; Wait for keystroke and convert to lower case
- ;
- CE_50:
- CALL GET_KEYSTROKE ;Check for keystroke
- JZ CE_50 ;None there, try again
- OR AL,20H ;Convert to lower case
- ;
- ; Restore the saved video data
- ;
- MOV SI,OUT_BUFF_END ;Old video is in output buffer
- MOV DI,0 ;Upper left corner of video
- MOV CX,5 ;Transfer 5 lines
- CE_60:
- PUSH CX ;Save line counter
- MOV CX,24D ;Transfer 24 char. per line
- REPNZ MOVSW
- ADD DI,112D ;Next line
- POP CX ;Restore line counter
- LOOP CE_60
- CMP AL,'y' ;Check for yes, all others no
- POP AX ;Restore exit code
- RET
- CONFIRM_EXIT ENDP
-
- ;---------------------------------------------------------------
- ; Draw the box and display the text in it.
- ; Input - SI points to the text strings
- ; Output - Current video stored in output buffer, text displayed
- ; in box.
- ; Changes - nothing
- ;---------------------------------------------------------------
- DISPLAY_BOX PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save registers
- PUSH BX
- PUSH CX
- PUSH DI
- PUSH SI
- ;
- ; Save the current video area in the output buffer
- ;
- CALL SWITCH_DS_ES
- MOV DI,ES:OUT_BUFF_END ;Use output buffer as temp stor.
- XOR SI,SI ;Upper left of video
- MOV CX,12 ;Save 12 lines
- DB_10:
- PUSH CX ;Save the line counter
- MOV CX,51 ;Save 51 columns
- REPNZ MOVSW
- ADD SI,58 ;Adjust to start of next line
- POP CX ;Restore line counter
- LOOP DB_10
- CALL SWITCH_DS_ES
- ;
- ; Blank that area of the screen
- ;
- XOR DI,DI ;Upper left of video
- MOV CX,12 ;Blank 12 lines
- DB_20:
- PUSH CX ;Save line counter
- MOV CX,51 ;Blank 51 characters
- DB_30:
- MOV AL,SPACE ;Space character
- CALL PUT_VIDEO_DATA ;Display the character
- MOV AL,70H ;Attribute
- CALL PUT_VIDEO_DATA
- LOOP DB_30
- ADD DI,58 ;Adjust to start of next line
- POP CX ;Restore line counter
- LOOP DB_20
- ;
- ; Draw the box
- ;
- MOV DI,166 ;First line of box
- CALL DRAW_LINE ;Display the horizontal line
- MOV DI,486 ;Second line of box
- CALL DRAW_LINE ;Display the horizontal line
- MOV DI,1286 ;Third line of box
- CALL DRAW_LINE ;Display the horizontal line
- MOV DI,1606 ;Fourth line of box
- CALL DRAW_LINE ;Display the horizontal line
- MOV BX,OFFSET BOX_CHAR ;Get a pointer to box corners
- MOV CX,20 ;Corners and vertical lines
- DB_40:
- MOV DI,[BX] ;Get offset to char location
- ADD BX,2 ;Point to character
- MOV AL,[BX] ;Get the character
- INC BX ;Next corner
- CALL PUT_VIDEO_DATA
- LOOP DB_40
- ;
- ; Draw the text in the box
- ;
- POP SI ;Get pointer to text
- PUSH SI
- MOV DI,348 ;Location for title line
- CALL DRAW_TEXT ;Display the line of text
- MOV DI,648 ;Next line of text
- CALL DRAW_TEXT ;Display the line of text
- MOV DI,808 ;Next line of text
- CALL DRAW_TEXT ;Display the line of text
- MOV DI,968 ;Next line of text
- CALL DRAW_TEXT ;Display the line of text
- MOV DI,1128 ;Next line of text
- CALL DRAW_TEXT ;Display the line of text
- MOV DI,1458 ;Next line of text
- MOV SI,OFFSET PRESS_ESC ;Display the press ESC to exit
- CALL DRAW_TEXT ;Display the line of text
- POP SI ;Restore registers
- POP DI
- POP CX
- POP BX
- POP AX
- RET
- DISPLAY_BOX ENDP
-
- ;---------------------------------------------------------------
- ; Draw horizontal line
- ; Input ES:DI points to location to start drawing the line
- ; Output - nothing
- ; Changes - AL, CX, DI
- ;---------------------------------------------------------------
- DRAW_LINE PROC NEAR
- MOV CX,45 ;45 Columns in line
- MOV AL,'═' ;Line draw character
- DL_10:
- CALL PUT_VIDEO_DATA ;Display the character
- INC DI ;Adjust past attribute
- LOOP DL_10
- RET
- DRAW_LINE ENDP
-
- ;---------------------------------------------------------------
- ; Display line of text
- ; Input - SI points to text DI points to video location
- ; Output - line of text is displayed on the screen
- ; Changes - AL, SI, DI
- ;---------------------------------------------------------------
- DRAW_TEXT PROC NEAR
- LODSB ;Get the text
- CMP AL,0 ;Is this the end of the string
- JZ DT_10 ;Yes
- CALL PUT_VIDEO_DATA ;Display the character
- INC DI
- JMP DRAW_TEXT
- DT_10:
- RET
- DRAW_TEXT ENDP
-
- ;---------------------------------------------------------------
- ; Restore the video saved to display a box
- ; Input - nothing
- ; Output - nothing
- ; Changes - nothing
- ;---------------------------------------------------------------
- RESTORE_BOX PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save registers
- PUSH CX
- PUSH DI
- PUSH SI
- MOV SI,OUT_BUFF_END ;Old video in output buffer
- XOR DI,DI ;Upper left corner of screen
- MOV CX,12 ;Line counter
- RB_10:
- PUSH CX ;Save line counter
- MOV CX,51 ;51 characters per line
- REPNZ MOVSW
- ADD DI,58 ;Next line
- POP CX ;Restore line counter
- LOOP RB_10
- POP SI ;Restore registers
- POP DI
- POP CX
- POP AX
- RET
- RESTORE_BOX ENDP
-
- ;---------------------------------------------------------------
- ; Display (U)pload or (D)ownload message and wait for response
- ; Input - Nothing
- ; Output -
- ; Changes - CX, SI, DI
- ;---------------------------------------------------------------
- TRANSFER_TYPE PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AX,OUT_BUFF_HEAD ;Wait until the out
- CMP AX,OUT_BUFF_TAIL ;buffer is empty
- JNZ TRANSFER_TYPE
- ;
- ; Display the (U)pload or (D)ownload message
- ;
- MOV SI,OFFSET TRANSFER_MESS ;Transfer message
- CALL DISPLAY_BOX
- ;
- ; Wait for a keystroke and convert to lower case
- ;
- TT_10:
- CALL GET_KEYSTROKE ;Check for a keystroke
- JZ TT_10 ;None there, try again
- OR AL,20H
- CALL RESTORE_BOX
- CMP AL,'u' ;Upload Requested ?
- JZ TT_20 ;Yes
- JMP TT_90 ;No, so continue
- TT_20: ;UPLOAD CODING HERE
- MOV LAST_KEY,0 ;Clear last key pressed
- CALL UPLOAD ;Ask for upload file
- CMP LAST_KEY,ESC_KEY ;ESC pressed ?
- JNZ TT_30 ;No
- JMP TT_180 ;Yes - return to PCREMOTE
- TT_30:
- MOV LAST_KEY,0 ;Clear last key pressed
- MOV SI,OFFSET UP_PATH_MESS ; Path message for upload
- CALL PATH ;Get destination Path
- CMP LAST_KEY,ESC_KEY ;ESC pressed ?
- JNZ TT_40 ;No
- JMP TT_180 ;Yes - return to PCREMOTE
- TT_40:
- MOV LAST_KEY,0 ;Clear last key pressed
- CALL MAKE_UP_COM ;Create ZCOPY EXEC com
- CLD ;Forward direction ptr.
- MOV SI,OFFSET ZCOPY ;DS:SI -- ZCOPY variable
- CALL SEND_STRING ;Send ZCOPY command line
- MOV SI,OFFSET HOST_COM ;DS:SI -- COM variable
- CALL SEND_STRING ;Send COM to host
- MOV AL,SPACE ;AL = SPACE
- CALL GET_SEND_CODE ;Get & send scan-code
- MOV SI,OFFSET PATH_STRING ;DS:SI -- Path variable
- MOV CX,PATH_LENGTH ;CX = Length of PATH
- CMP CX,0 ;Default Path ?
- JE TT_60 ;Yes...
- TT_50: ;No...
- LODSB ;AL = next character
- CALL GET_SEND_CODE ;Get & send scan-code
- LOOP TT_50 ;All characters sent ?
- MOV AL,SPACE ;AL = SPACE
- CALL GET_SEND_CODE ;Get & send scan-code
- TT_60:
- MOV SI,OFFSET PARM_STRING ;DS:SI -- PARM variable
- MOV CX,9D
- TT_70:
- LODSB ;AL = Next character
- CALL GET_SEND_CODE ;Get & send scan-code
- LOOP TT_70 ;All characters sent ?
- MOV AL,CR ;AL = carriage return
- CALL GET_SEND_CODE ;Get & send scan-code
- TT_80:
- MOV AX,OUT_BUFF_HEAD ;Get the buff head ptr
- CMP AX,OUT_BUFF_TAIL ;Test for data
- JNZ TT_80 ;Wait until buffer empty
- MOV EXEC_VAL,3D ;Tell EXEC to upload
- CALL EXEC_ZCOPY ;Shell to DOS & EXEC ZCOPY
- JMP TT_170 ;Transfer complete, exit
- TT_90:
- CMP AL,'d' ;Download Requested ?
- JZ TT_100 ;Yes
- JMP TT_180 ;No so return to PCREMOTE
- TT_100: ;DOWNLOAD CODING HERE
- MOV LAST_KEY,0 ;Clear last key pressed
- CALL DOWNLOAD ;Ask for filename
- CMP LAST_KEY,ESC_KEY ;ESC pressed ?
- JNZ TT_110 ;No
- JMP TT_180 ;Yes, return to PC_REMOTE
- TT_110:
- MOV LAST_KEY,0 ;Clear last key pressed
- MOV SI,OFFSET DN_PATH_MESS ; Path message for download
- CALL PATH ;Get destination Path
- CMP LAST_KEY,ESC_KEY ;ESC pressed ?
- JNZ TT_120 ;No
- JMP TT_180 ;Yes, return to PC_REMOTE
- TT_120:
- MOV LAST_KEY,0 ;Clear last key pressed
- CALL MAKE_DN_COM ;Create ZCOPY EXEC com
- CLD ;Forward direction flag
- MOV SI,OFFSET ZCOPY ;DS:SI -- ZCOPY variable
- CALL SEND_STRING ;Send ZCOPY command
- MOV SI,OFFSET UPDN_STRING ;DS:SI -- file variable
- MOV CX,DN_LENGTH ;CX = length of filename
- CMP CX,0 ;Default Filename
- JE TT_140 ;Yes...
- TT_130: ;No...
- LODSB ;AL = next character
- CALL GET_SEND_CODE ;Get & send scan-code
- LOOP TT_130 ;All characters sent ?
- MOV AL,SPACE ;AL = SPACE
- CALL GET_SEND_CODE ;Get & send scan-code
- TT_140:
- MOV SI,OFFSET HOST_COM ;DS:SI -- Com variable
- CALL SEND_STRING ;Send COM variable
- MOV AL,SPACE ;AL = SPACE
- CALL GET_SEND_CODE ;Get & send scan-code
- MOV SI,OFFSET PARM_STRING ;DS:SI -- PARM variable
- MOV CX,9D
- TT_150:
- LODSB ;AL = next character
- CALL GET_SEND_CODE ;Get & send scan-code
- LOOP TT_150 ;All characters sent ?
- MOV AL,CR ;AL = carriage return
- CALL GET_SEND_CODE ;Get & send scan-code
- TT_160:
- MOV AX,OUT_BUFF_HEAD ;Get buffer head ptr
- CMP AX,OUT_BUFF_TAIL ;Test for data in buff
- JNZ TT_160 ;Wait for buffer empty
- MOV EXEC_VAL,2D ;Tell EXEC to download
- CALL EXEC_ZCOPY ;Shell to DOS - EXEC ZCOPY
- JMP TT_170
- TT_170:
- MOV AX,WORD PTR CLEAR_CODE ;Tell the caller to clear
- JMP TT_190 ;the remote's screen
- TT_180:
- MOV AX,WORD PTR TRANSFER_CODE ;Tell the caller that
- TT_190: ;screen doesn't need to
- RET ;be rewritten.
- TRANSFER_TYPE ENDP
-
- ;------------------------------------------------------------
- ; Display upload message then wait for filename(s).
- ; Input - Nothing
- ; Output -
- ; Changes - CX,SI,DI
- ;
- ;------------------------------------------------------------
- UPLOAD PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AX,OUT_BUFF_HEAD ;Wait until the out
- CMP AX,OUT_BUFF_TAIL ;buffer is empty
- JNZ UPLOAD
- MOV SI,OFFSET UPLOAD_MESS ;Upload message
- CALL DISPLAY_BOX
- PUSH DX ;Save register
- MOV DH,7 ;Put cursor in row 8
- MOV DL,5 ;Put cursor in column 6
- CALL PUT_CURSOR ;Set Cursor
- POP DX ;Restore register
- PUSH ES ;Store ES
- PUSH DS ;Store DS
- POP ES ;ES = DS
- MOV DI,OFFSET UPDN_STRING ;ES:DI -> UP_string
- MOV CX,42D ;MAX length = 42
- CALL GETSTRING ;Receive file
- MOV LAST_KEY,AL ;Save last key
- MOV UP_LENGTH,CX ;Save length
- CMP UP_LENGTH,0 ;Any file selected ?
- JNE UP_10 ;Yes
- MOV LAST_KEY,ESC_KEY ;No...Return (esc)
- UP_10:
- POP ES ;Restore ES
- CALL RESTORE_BOX
- RET
- UPLOAD ENDP
-
- ;------------------------------------------------------------
- ; Display download message then wait for response.
- ; Input - Nothing
- ; Output -
- ; Changes - CX,SI,DI
- ;------------------------------------------------------------
- DOWNLOAD PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AX,OUT_BUFF_HEAD ;Wait until the
- CMP AX,OUT_BUFF_TAIL ;out buffer is empty
- JNZ DOWNLOAD
- MOV SI,OFFSET DOWNLOAD_MESS ;Download message
- CALL DISPLAY_BOX
- PUSH DX ;Save DX register
- MOV DH,7 ;Put cursor in row 8
- MOV DL,5 ;Put cursor in column 6
- CALL PUT_CURSOR ;Put cursor there
- POP DX ;Restore register
- PUSH ES ;Store ES
- PUSH DS ;Store DS
- POP ES ;ES = DS
- MOV DI,OFFSET UPDN_STRING ;ES:DI -> DN_string
- MOV CX,42D ;MAX length = 42
- CALL GETSTRING ;Get filename
- MOV LAST_KEY,AL ;Save last key
- MOV DN_LENGTH,CX ;Save length
- CMP DN_LENGTH,0 ;File selected ?
- JNE DN_10 ;Yes
- MOV LAST_KEY,ESC_KEY ;No... return (esc)
- DN_10:
- POP ES ;Restore ES
- CALL RESTORE_BOX
- RET
- DOWNLOAD ENDP
-
- ;----------------------------------------------------------------------
- ; Display the path request screen & prompt user to input path name.
- ; Input - SI points to display message for transfer
- ; Output - Path Message Displayed on screen.
- ; Changes - CX,SI,DI
- ;----------------------------------------------------------------------
- PATH PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- MOV AX,OUT_BUFF_HEAD ; Wait until the
- CMP AX,OUT_BUFF_TAIL ; out buffer is empty
- JNZ PATH
- CALL DISPLAY_BOX
- PUSH DX ; Save DX Register
- MOV DH,7 ; Put cursor in row 8
- MOV DL,5 ; Put cursor in col 6
- CALL PUT_CURSOR ; Put cursor there
- POP DX ; Restore DX
- PUSH ES ; Store ES
- PUSH DS ; Store DS
- POP ES ; ES = DS
- MOV DI,OFFSET PATH_STRING ; ES:DI -> Path_string
- MOV CX,42D ; Max length = 42
- CALL GETSTRING ; Get path
- MOV LAST_KEY,AL ; Save last key
- MOV PATH_LENGTH,CX ; Save length
- ;
- ; Validate and correct (modify) pathname if ZCOPY will not accept the
- ; string entered for the pathname.
- ; i.e.- C:\ is acceptable whereas C: is unacceptable
- ; C:\DOS is acceptable whereas C:\DOS\ is unacceptable.
- ;
- CMP LAST_KEY,ESC_KEY ; ESC key pressed ?
- JE PATH_20 ; Yes, so skip pathname edit
- MOV SI,OFFSET PATH_STRING ; SI->1st char of path name
- ADD SI,PATH_LENGTH ; SI->1 char after pathname
- DEC SI ; SI->Last char of pathname
- LODSB ; Pick off last char
- CMP AL,':' ; Is last char a colon
- JNE PATH_10 ; No, check other chars.
- PUSH SI ; Save SI into DI
- POP DI ; DI = SI
- MOV AL,'\' ; Add backslash to pathname
- STOSB ; Store the backslash
- INC PATH_LENGTH ; Add one to length of path
- JMP PATH_20 ; Editting is complete
- PATH_10:
- CMP AL,'\' ; Is last char a backslash
- JNE PATH_20 ; No, skip pathname edit
- DEC SI ; SI -> Last char again
- DEC SI ; SI -> 2nd last char
- LODSB ; Pick off 2nd last char
- CMP AL,':' ; 2nd last char a colon ?
- JE PATH_20 ; Yes, so skip edit.
- PUSH SI ; Store SI for DI
- POP DI ; DI-> Last char of pathname
- MOV AL,SPACE ; Clear last char of path
- STOSB ; Store blank
- DEC PATH_LENGTH ; Subtract 1 from path length
- PATH_20:
- POP ES
- CALL RESTORE_BOX
- RET
- PATH ENDP
-
- ;----------------------------------------------------------------------
- ; Create the Upload command string that the REMOTE computer EXECS
- ;----------------------------------------------------------------------
- MAKE_UP_COM PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Store registers
- PUSH CX
- PUSH DS
- PUSH ES
- PUSH DI
- PUSH SI
- PUSHF
- PUSH CS
- PUSH CS
- POP DS ;DS -> CS
- POP ES ;ES -> CS
- CLD ;Forward Direction Flag
- MOV DI,OFFSET UPDNLOAD_COM ;DI -> 1st char of upload com
- ADD DI,10D ;DI -> 10th char of upl. com
- MOV AL,SPACE ;Reset com string w/ 89
- MOV CX,89D ; blanks
- MUC_10:
- STOSB ;Fill sting with AL
- LOOP MUC_10 ;89 chars complete ?
- SUB DI,89D ;DI -> 10th char of upl. com
- MOV SI,OFFSET UPDN_STRING ;SI -> 1st char of upl. file
- MOV CX,UP_LENGTH ;CX = length of string
- MUC_20:
- LODSB ;AL = char from filename
- STOSB ;Upl. com gets char
- LOOP MUC_20 ;All chars copied ?
- MOV AL,SPACE ;Place a blank char at the
- STOSB ; end of filename
- MOV SI,OFFSET REMOTE_COM ;SI -> 1st char of comm var.
- MOV CX,4D ;Pick off 4 characters
- MUC_30:
- LODSB ;Pick off 1 char
- STOSB ;Place in upl. com string
- LOOP MUC_30 ;Entire string done ?
- MOV AL,SPACE ;Place a blank at end of comm
- STOSB ; string in upl. com string
- MOV SI,OFFSET PARM_STRING ;SI -> 1st char of parm
- ADD SI,3D ;SI -> 4th char of parm
- MOV CX,5D ;Pick off 5 chars from parm
- MUC_40:
- LODSB ;Pick off 1 char
- STOSB ;Place char in upl. com
- LOOP MUC_40 ;6 characters done yet ?
- MUC_50:
- MOV AL,CR ;Carriage return
- STOSB
- MOV AL,0 ;0 to end string
- STOSB
- ;
- ; Length of UPDNLOAD_COM must be inserted in the first character of the
- ; string ("?/c zcopy..."), therefore the length must be determined.
- ;
- MOV SI,OFFSET UPDNLOAD_COM ;SI-> 1st char of string
- CALL GET_STRING_LEN ;CX = Length of string
- MOV AL,CL ;Ready AL for STOSB instruct.
- MOV DI,OFFSET UPDNLOAD_COM ;DI-> 1st char of string
- STOSB ;Store AL in string
- MUC_RET:
- POPF ;Restore registers & flags
- POP SI
- POP DI
- POP ES
- POP DS
- POP CX
- POP AX
- RET
- MAKE_UP_COM ENDP
-
- ;----------------------------------------------------------------------
- ; Creates the download command string that the REMOTE computer EXECS
- ;----------------------------------------------------------------------
- MAKE_DN_COM PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Store registers
- PUSH CX
- PUSH DS
- PUSH ES
- PUSH DI
- PUSH SI
- PUSHF
- PUSH CS
- PUSH CS
- POP DS ;DS -> CS
- POP ES ;ES -> CS
- CLD ;Forward direction flag
- MOV DI,OFFSET UPDNLOAD_COM ;DI -> Download command string
- ADD DI,10D ;DI -> 11th char of command
- MOV AL,SPACE ;Reset command w/ blanks
- MOV CX,89D ; 89 of them...
- MDC_10:
- STOSB ;Store the blank in command
- LOOP MDC_10 ;56 chars. complete ?
- SUB DI,89D ;Reset DI to 11th char.
- MOV SI,OFFSET REMOTE_COM ;SI -> (C)OMx
- MOV CX,4D ;Transfer COMx to com. line
- MDC_20:
- LODSB ;Pick off a char into AL
- STOSB ;Move AL into command
- LOOP MDC_20 ;All 4 chars copied ?
- MOV AL,SPACE ;Move a blank in after COMx
- STOSB ;Store blank
- CMP PATH_LENGTH,0 ;Does target directory exist?
- JE MDC_40 ;No, skip target dir. copy
- MOV SI,OFFSET PATH_STRING ;Yes, SI -> 1st char of dir.
- MOV CX,PATH_LENGTH ;CX = length of path string
- MDC_30:
- LODSB ;Pick off one char
- STOSB ;Store char in command line
- LOOP MDC_30 ;All chars. copied ?
- MOV AL,SPACE ;Move in a blank after dir.
- STOSB ;Store blank in line
- MDC_40:
- MOV SI,OFFSET PARM_STRING ;SI -> 1st char of parm
- ADD SI,3D ;SI -> 4th char of parm
- MOV CX,5D ;Move in last 5 characters
- MDC_50:
- LODSB ;Pick off one char.
- STOSB ;Copy char in command
- LOOP MDC_50 ;All 6 chars copied ?
- MDC_60:
- MOV AL,CR ;Carriage return
- STOSB
- MOV AL,0 ;End string with a 0
- STOSB
- ;
- ; Length of download_com must be inserted in the first character of the
- ; string ("?/c zcopy..."), therefore the length must be determined.
- ;
- MOV SI,OFFSET UPDNLOAD_COM ;SI-> 1st char of string
- CALL GET_STRING_LEN ;CX = Length of string
- MOV AL,CL ;Ready AL for STOSB instruct.
- MOV DI,OFFSET UPDNLOAD_COM ;DI-> 1st char of string
- STOSB ;Store al in string
- MDC_RET:
- POPF ;Restore registers
- POP SI
- POP DI
- POP ES
- POP DS
- POP CX
- POP AX
- RET
- MAKE_DN_COM ENDP
-
- ;----------------------------------------------------------------------
- ; Get string length determines the length of the string that DS:SI is
- ; pointing to. The length is returned in the CX register.
- ; Input - DS:SI points to the first character of the associated string.
- ; Output - CX = Length of the string.
- ; Changes - CX
- ;----------------------------------------------------------------------
- GET_STRING_LEN PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Store registers
- PUSH SI
- PUSHF
- CLD ;Go forward in variables
- XOR CX,CX ;Reset CX (counter) to zero
- GSL_10:
- LODSB ;Pick off one character
- OR AL,AL ;Is the character a zero ?
- JZ GSL_20 ;Yes, return w/ length = CX
- INC CX ;No... bump character counter
- JMP GSL_10 ;Get another character
- GSL_20:
- POPF ;Restore registers
- POP SI
- POP AX
- RET
- GET_STRING_LEN ENDP
-
- ;----------------------------------------------------------------------
- ; Get current cursor position
- ; Input - Nothing
- ; Output - DX contains current cursor position
- ; Changes - DX
- ;----------------------------------------------------------------------
- GET_CURSOR PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Push registers
- PUSH BX
- MOV BH,0 ;First page
- MOV AH,3
- INT 10H ;DOS call
- POP BX ;Restore registers
- POP AX
- RET
- GET_CURSOR ENDP
-
- ;--------------------------------------------------------------------
- ; Places cursor in the DX position.
- ; Input - DX
- ; Output - Cursor placement
- ; Changes - Nothing
- ;--------------------------------------------------------------------
- PUT_CURSOR PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Push registers
- PUSH BX
- MOV AH,2
- MOV BH,0 ;First page
- INT 10H ;DOS call
- POP BX ;Restore registers
- POP AX
- RET
- PUT_CURSOR ENDP
-
- ;--------------------------------------------------------------------
- ; Inputs a character string from the keyboard. Characters will be
- ; accepted until the user presses the return, ESC or CX chars. have
- ; been received from keyboard.
- ; Input - ES:DI Points to the buffer that is to receive the string.
- ; CX Contains the length of the input buffer.
- ; Output -CX Contains the actual length of the character string.
- ; AX Contains the last keystroke
- ; The specified buffer contains the character string that was
- ; entered.
- ;---------------------------------------------------------------------
- GETSTRING PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH BX
- PUSH DI ;Store Registers
- PUSH DX
- PUSHF
- CLD ;Direction Flag Forward
- XOR BH,BH ;Screen page 0
- XOR DX,DX ;Reset character counter
- GS_10:
- XOR AH,AH ;Function 0 -INT16H- Read key
- INT 16H ;Read character from keys
- CMP AL,CR ;Carriage Return ?
- JE GS_30 ;Yes
- CMP AL,ESC_KEY ;Escape key ?
- JE GS_30 ;Yes
- CMP AL,BS ;Back space ?
- JNE GS_14 ;No
- CMP DX,0 ;Yes, but 1st char. ?
- JE GS_10 ;Yes, so skip BS & get a key
- GS_14:
- STOSB ;No... Store Character
- INC DX ;Bump character counter
- MOV AH,14 ;Function 14 -INT10H-
- INT 10H ;Display character
- CMP AL,BS ;Was last char a backspace ?
- JNE GS_20 ;No
- GS_15:
- SUB DX,2 ;Decrement char count twice
- SUB DI,2 ;Move PTR back 2 spaces
- ADD CX,2 ;Move in two spaces
- MOV AH,14 ;Display character interrupt
- MOV AL,SPACE ;Space
- INT 10H ;Display character
- MOV AH,14 ;Display character interrupt
- MOV AL,BS ;Backspace
- INT 10H ;Display character
- GS_20:
- LOOP GS_10 ;Size = # of characters
- GS_30:
- MOV CX,DX ;Save # of chars. in CX
- POPF ;Restore Registers
- POP DX
- POP DI
- POP BX
- RET
- GETSTRING ENDP
-
- ;------------------------------------------------------------
- ; Input - DS:SI must point to the 1st char of the string to be
- ; sent to the host computer.
- ; Output - The entire string is sent to the host computer until
- ; a ZERO (end of string) is found.
- ; Changes - SI,AL
- ;------------------------------------------------------------
- SEND_STRING PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSHF ;Store Direction Flag
- CLD
- SZ_10:
- LODSB ;Get AL
- CMP AL,0 ;Done with string ?
- JE SZ_EXIT ;Yes...
- CALL GET_SEND_CODE ;No...get & send scan
- JMP SZ_10 ;Repeat until done
- SZ_EXIT:
- POPF ;Restore Direction Flag
- RET
- SEND_STRING ENDP
-
- ;------------------------------------------------------------
- ; Input - AL contains the ASCII code of the character to be
- ; sent to the host computer.
- ; Output - AX is sent to the host computer where
- ; AL is ASCII code
- ; AH is the associated scan code for the ASCII code
- ; Changes - Nothing
- ;------------------------------------------------------------
- GET_SEND_CODE PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Store Registers
- PUSH BX
- PUSH CX
- PUSH SI
- PUSHF
- CMP AL,'a' ;Small Case letter ?
- JL GSC_10 ;No ....
- CMP AL,'z'
- JG GSC_10 ;No ....
- SUB AL,32D ;Yes ....
- GSC_10:
- MOV BL,AL ;Save ASCII code
- MOV CX,0 ;Reset counter into var.
- MOV SI,OFFSET ASCII_CODE ;DS:SI -> ASCII variable
- CLD ;Forward
- GSC_20:
- CMP CX,70D ;Invalid ASCII ?
- JE GSC_EXIT ;Yes...
- INC CX ;Bump counter
- LODSB ;AL = next char in var.
- CMP AL,BL ;Find correct offset ?
- JNE GSC_20 ;No...
- GSC_30: ;Yes... so bump that far
- MOV SI,OFFSET SCAN_CODE ;into scan_code var and
- CLD ;pick off that scan_code.
- GSC_40:
- LODSB
- LOOP GSC_40
- GSC_50:
- MOV AH,AL ;AH = scan-code
- MOV AL,BL ;AL = ASCII code
- CALL SEND_KEYSTROKE ;Send AX
- GSC_EXIT:
- POPF ;Restore registers
- POP SI
- POP CX
- POP BX
- POP AX
- RET
- GET_SEND_CODE ENDP
-
- ;-----------------------------------------------------------------
- ; Execute ZCOPY (upload/download) or shell to DOS and return to
- ; the calling program.
- ;-----------------------------------------------------------------
- EXEC_ZCOPY PROC NEAR
- CMP BYTE PTR NOEXEC,0FFH
- JNZ EZ_10
- JMP EZ_EXIT
- EZ_10:
- PUSH AX ;Store all registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH SI
- PUSH DI
- PUSH DS
- PUSH ES
- PUSH BP
- PUSH CS
- PUSH CS
- POP DS
- POP ES
- CMP EXEC_VAL,1D ;Shelling to DOS ?
- JE EZ_20 ;Yes, display shell prompt
- CMP EXEC_VAL,2D ;Downloading from host ?
- JE EZ_30 ;Yes, display transfer prompt
- CMP EXEC_VAL,3D ;Uploading from host ?
- JE EZ_30 ;Yes, display transfer prompt
- JMP EZ_60 ;EXEC_VAL has wrong value !
- EZ_20:
- MOV AX,OFFSET NUL_TAIL ;Shell to DOS
- MOV SI,OFFSET SHELL_PROMPT ;Notify user of shell
- JMP EZ_40
- EZ_30:
- MOV AX,OFFSET UPDNLOAD_COM ;Uploading
- MOV SI,OFFSET TRANSFER_PROMPT ;Notify transferring
- EZ_40:
- MOV PAR_BLK+2,AX ;EXEC
- CALL CLEAR_SCREEN ;Clear remote screen
- CALL GET_STRING_LEN ;Get string length of DS:SI
- PUSH ES ;Store registers & flags
- PUSH DI
- PUSHF ;Store flag
- MOV AX,VIDEO_SEGMENT ;AX->1st char of video segment
- MOV ES,AX ;ES->1st char of video segment
- XOR DI,DI ;ES:DI-> 1st char of video seg
- CLD ;Forward in video segment
- EZ_50:
- LODSB ;Pick off char in string
- CALL PUT_VIDEO_DATA ; and place in video segment
- MOV AL,70H ;Place reverse video
- CALL PUT_VIDEO_DATA ; in video segment
- LOOP EZ_50 ;All characters displayed ?
- POPF ;Restore flags
- POP DI ;Restore registers
- POP ES
- MOV DH,2D ;Row 2
- XOR DL,DL ;Col 0
- CALL PUT_CURSOR ;Place cursor on screen
- CALL SET_ENV
- CMP BYTE PTR NOEXEC,0FFH
- JZ EZ_60
- PUSH DS
- PUSH ES
- MOV OLD_SS,SS
- MOV OLD_SP,SP
- MOV BX,OFFSET PAR_BLK
- LDS DX,CS:COMSPC
- MOV AX,4B00H
- INT 21H
- ;
- ; return from DOS exec
- ;
- MOV SS,CS:OLD_SS
- MOV SP,CS:OLD_SP
- MOV ES,CS:PAR_BLK
- MOV AH,49H
- INT 21H
- POP ES
- POP DS
- EZ_60:
- POP BP
- POP ES
- POP DS
- POP DI
- POP SI
- POP DX
- POP CX
- POP BX
- POP AX
- EZ_EXIT:
- RET
- EXEC_ZCOPY ENDP
-
- ;-----------------------------------------------------------------------
- ; Find the string pointed to by DS:SI in the segment pointed to by ES
- ; ES:0000 is assumed to contain null terminated stings.
- ; Input - ES points to environment segment
- ; SI points to search string
- ; Output - Zero set - could not locate string
- ; Zero reset - found the string, ES:DI points to end of string
- ; found. DI is also count of characters up to
- ; end of string.
- ; Changes -
- ;-----------------------------------------------------------------------
- FIND_SI PROC NEAR
- XOR DI,DI ;Zero environment pointer
- FNDSI1: MOV BX,SI ;Save the source string
- CMP BYTE PTR ES:[DI],00 ;End of environment space?
- JNZ FNDSI2 ; no
- RET ; yes, return with zero set
- FNDSI2:
- MOV AL,[BX] ;Get source string character
- OR AL,AL ;End of string?
- JZ FNDSI4 ; yes
- CMP AL,ES:[DI] ; no, Same as environment char?
- JNZ FNDSI3 ; no, string doesn't match
- INC BX ; yes, check the next char
- INC DI ; in both strings
- JMP FNDSI2
- FNDSI3:
- XOR AL,AL ;Null string terminator
- MOV CX,-0001 ;Make sure to find string end
- CLD
- REPNZ SCASB ;Find the end of this string
- JMP FNDSI1 ;Test the next string
- FNDSI4:
- XOR AX,AX ;Located the string
- INC AX ;Reset the zero flag
- RET
- FIND_SI ENDP
-
- ;-----------------------------------------------------------------
- ; SET NEW ENVIRONMENT
- ;
- ;-----------------------------------------------------------------
-
- SET_ENV PROC NEAR
- PUSH DS
- PUSH ES
- MOV ES,DS:[002CH] ;Environment segment pointer
- MOV SI,OFFSET PMTSTR ;Pointer to "PROMPT="
- CALL FIND_SI ;Is "PROMPT=" in environment?
- JNZ GOTPMT ; yes
- XOR DI,DI ; no, set length to 0
- ;
- ; DI = number of characters in environment to end of "PROMPT=" string.
- ;
- GOTPMT:
- MOV BX,DI ;Save the count
- XOR DI,DI
- MOV AX,DI
- MOV CX,0FFFFH
- CLD
- REPNZ SCASW ;Locate the end of the string
- MOV AX,PMTLGT
- ADD AX,DI
- CMP BX,0000
- JNZ PMTHER
- ADD AX,(OFFSET PCRSTR) - (OFFSET DFTPMT)
- PMTHER:
- MOV CL,04
- SHR AX,CL
- INC AX
- SUB DI,BX
- PUSH DI
-
- PUSH BX
- MOV BX,AX ;number of paragraphs request
- MOV AH,48H ;malloc
- INT 21H
- JNC NOERR
- MOV BYTE PTR NOEXEC,0FFH
-
- NOERR: MOV PAR_BLK,AX ;segment to malloc
- MOV ES,AX ;segment to malloc
- XOR DI,DI
- CLD
- POP CX
- CMP CX,0000
- JNZ DOITAL
- MOV CX,PMTLGT
- MOV WORD PTR PMTLGT,0000
- ADD CX,(OFFSET PCRSTR) - (OFFSET DFTPMT)
- MOV SI,OFFSET DFTPMT
- REP MOVSB
- MOV SI,OFFSET GODPMT
- MOV CX,(OFFSET PMTSTR) - (OFFSET GODPMT)
- REP MOVSB
- ;
- ; FROM ADD TO USERS PROMPT
- ;
- DOITAL:
- MOV AX,DS:[002CH]
- MOV DS,AX
- XOR SI,SI
- JCXZ PMTDON
- REP MOVSB
- ;
- ; IF NO PROMPT=', NEW PROMPT STORED AND WHOLE ENV STORED NEXT
- ;
- PMTDON:
- PUSH DS
- PUSH SI
- PUSH CS
- POP DS
- MOV SI,OFFSET PCRSTR
- MOV CX,PMTLGT
- JCXZ NOPMT
- REP MOVSB
- ;
- ; ANY PROMPT STORED?
- ;
- NOPMT:
- POP SI
- POP DS
- POP CX
- REP MOVSB
- POP ES
- POP DS
- RET
- SET_ENV ENDP
-
- ;----------------------------------------------------------------------
- GET_COMSPEC PROC NEAR
- PUSH ES
- MOV PAR_BLK+04,DS
- MOV AX,DS:[002CH]
- MOV PAR_BLK,AX
- MOV ES,AX
- MOV SI,OFFSET COM_VAR
- CALL FIND_SI
- MOV CS:COM_SEG,ES
- MOV CS:COM_OFS,DI
- JNZ NO_FND
- MOV BYTE PTR NOEXEC,0FFH
- NO_FND:
- POP ES
- RET
- GET_COMSPEC ENDP
-
- ;----------------------------------------------------------------------
- ; Switch ES and DS
- ; Input - Nothing
- ; Output - ES is in DS and DS is in ES
- ; Changes - ES, DS
- ;----------------------------------------------------------------------
- SWITCH_DS_ES PROC NEAR
- PUSH ES ;Push ES
- PUSH DS ;Push DS
- POP ES ;Switch ES
- POP DS ;with DS
- RET
- SWITCH_DS_ES ENDP
-
- ;----------------------------------------------------------------------
- ; Put the keystroke data into the output buffer to be sent to unattended
- ; system
- ; Input - AX - keystroke data
- ; Output - Nothing
- ; Changes - Nothing
- ;----------------------------------------------------------------------
- SEND_KEYSTROKE PROC NEAR
- ASSUME CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
- PUSH AX ;Save it
- MOV AH,1 ;Use the output buffer
- MOV AL,0FEH ;Sync byte, to expect key data
- CALL PUT_BUFF_DATA ;Put AL into the output buffer
- POP AX ;Get AL back
- PUSH AX ;Save AH
- MOV AH,1 ;Use the output buffer
- CALL PUT_BUFF_DATA ;Put ASCII code in out buffer
- POP AX ;Get AH back
- PUSH AX ;Save keystroke
- MOV AL,AH ;Move it to AL
- MOV AH,1 ;Use the output buffer
- CALL PUT_BUFF_DATA ;Put scan code in out buffer
- POP AX ;Restore keystroke
- RET
- SEND_KEYSTROKE ENDP
-
- ;======================================================================
- LAST_BYTE EQU $
- CSEG ENDS
- END START
-