home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 02 / pcremot2.asm < prev    next >
Assembly Source File  |  1992-01-02  |  122KB  |  3,771 lines

  1.     TITLE    PCREMOT2 - Unattended Computer Access - 1991 by Terry Lahman
  2.     PAGE    78,132
  3. ;======================================================================
  4. ;
  5. ;  PCREMOT2 - An unattended computer access utility.  Allows access to an
  6. ;  unattended computer from a manned computer.    The unattended computer
  7. ;  executes the TSR portion of the program and waits for the manned
  8. ;  computer to call.  For use with text only programs.    Like using the
  9. ;  phone lines and modems as a long extension cord for your keyboard
  10. ;  and monitor.
  11. ;
  12. ;    Usage:    PCREMOT2 [ /M ] [ /# ] [ /B# ] [ /D ] [ /S ] [ /N ] [ /U ] [ /? ]
  13. ;        
  14. ;        [ /M  ]  = "Manned" mode (used on remote system)
  15. ;        [ /#  ]  = 1 - 4, Communication port used
  16. ;        [ /B# ]  = Baud rate 1=1200, 2=2400, 4=4800, 9=9600
  17. ;                     19=19200, 3=38400
  18. ;        [ /D  ]  = "Desnow" flag (used on CGA monitors)
  19. ;        [ /S  ]  = Smiley face displayed (used on host system)
  20. ;        [ /N  ]  = Null modem cable connecting 2 systems
  21. ;        [ /U  ]  = Uninstall (used on host computer to remove from memory) "
  22. ;        [ /?  ]  = Display help screen
  23. ;
  24. ;======================================================================
  25. CSEG    SEGMENT PARA PUBLIC 'CODE'
  26.     ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  27.  
  28. BS        EQU    8
  29. CR        EQU    13
  30. LF        EQU    10
  31. SPACE        EQU    32
  32. ESC_KEY        EQU    1BH
  33.  
  34. ;----------------------------------------------------------------------
  35. ;  Start of code
  36. ;----------------------------------------------------------------------
  37.         ORG    100H            ;Starting offset for .com
  38. START:        JMP    INITIALIZE        ;Jump over resident code
  39.         DW    OFFSET CONFIG - $    ;Offset to config parameters
  40.  
  41. ;----------------------------------------------------------------------
  42. ;  Data storage
  43. ;----------------------------------------------------------------------
  44.  
  45. COPYRIGHT    DB    "PCREMOT2 Version 1.0 (c) 1989, 1991 Ziff Communications Co."
  46.         DB    CR,LF,"        PC Magazine ",254," by Terry Lahman & Kevin Sims"
  47.         DB    CR,LF,"$",26
  48. CONNECT_FLAG    DB    0            ;0=not connected
  49.                         ;1=connected to manned system
  50. ACT_FLAG    DB    0            ;0=unattended prog not active
  51.                         ;1=unattended program is active
  52.                         ; do not run again
  53. OLDINT_8    DW    0,0            ;Old timer vector
  54. OLDINT_21    DW    0,0            ;Old DOS vector
  55. OLDINT_COMM    DW    0,0            ;Old communications vector
  56. INSTALLED_SEG    DW    0            ;Segment of resident program
  57. SET_VEC     DW    2500H            ;DOS set vector call
  58. SLEEP_FLAG    DB    0            ;0=pcremote is awake
  59.                         ;1=pcremote is asleep
  60.                         ;needs to sleep during init.
  61. CURRENT_SPEED    DB    0            ;Currently selected speed
  62. SPEED_COUNT    DB    0            ;Change speed once a second
  63. COMM_PORT    DW    0            ;Comm port address
  64. COMM_INT_STA    DB    0            ;Comm port interrupt status
  65.                         ;0=not transmitting data
  66.                         ;1=transmitting data
  67. VIDEO_COPY    DW    0            ;Address of video ram copy
  68. VIDEO_SEGMENT    DW    0            ;Segment register for vid ram
  69. SHIFT_STATUS    DB    0            ;Current status of shift byte
  70. STACK_TOP    DW    INITIALIZE+256D     ;Top of stack for unattended
  71. OLD_SS        DW    0            ;Old stack segment
  72. OLD_SP        DW    0            ;Old stack pointer
  73. TEMP_REG    DW    0            ;Temp storage for register
  74. CURSOR_POSITION DW    0            ;Old cursor position
  75. VID_RAM_OFFSET    DW    0            ;Current compare offset
  76. ASCII_FLAG    DB    0            ;0=no data is pending
  77.                         ;1=received a FE
  78.                         ;2=received ASCII char
  79.                         ;4=received scan code
  80. SHIFT_FLAG    DB    0            ;0=no data is pending
  81.                         ;1=received a FD
  82. KEY_ONE     DB    0            ;ASCII char received
  83. KEY_TWO     DB    0            ;Scan code received
  84. BAUD_RATE    DB    0,60H            ;1200 BAUD divisor MSB LSB
  85.         DB    0,30H            ;2400 BAUD divisor MSB LSB
  86.         DB    0,18H            ;4800 BAUD divisor MSB LSB
  87.         DB    0,0CH            ;9600 BAUD divisor MSB LSB
  88.         DB    0,06H            ;19200 BAUD divisor MSB LSB
  89.         DB    0,03H            ;38400 BAUD divisor MSB LSB
  90. IN_BUFF_SIZE    EQU    256D            ;Size for input buffer
  91. OUT_BUFF_SIZE    EQU    256D            ;Size for output buffer
  92. IN_BUFF_HEAD    DW    ?            ;Pointer to input buffer head
  93. IN_BUFF_TAIL    DW    ?            ;Pointer to input buffer tail
  94. IN_BUFF_BEGIN    DW    ?            ;Pointer to input buffer begin
  95. IN_BUFF_END    DW    ?            ;Pointer to input buffer end
  96. OUT_BUFF_HEAD    DW    ?            ;Pointer to output buffer head
  97. OUT_BUFF_TAIL    DW    ?            ;Pointer to output buffer tail
  98. OUT_BUFF_BEGIN    DW    ?            ;Pointer to output buffer begin
  99. OUT_BUFF_END    DW    ?            ;Pointer to output buffer end
  100. BLOCK_SIZE    EQU    16D            ;Block transfer size in words
  101. BLOCK_SIZEX2    EQU    BLOCK_SIZE*2        ;Block transfer size in bytes
  102. BLOCK_COUNT    DB    ?            ;Block number being processed
  103. BLOCK_POINTER    DW    0            ;Points to current video block
  104. TEMP_VIDEO_PTR    DW    ?            ;Pointer to temp video storage
  105. CR_COUNT    DB    ?            ;Number of CRs for speed sync
  106. MODEM_ATTENTION DB    CR,"AT",CR,0
  107. MODEM_SETUP1    DB    "ATE0 S12=40 Q0 V0 X1 S0=0",CR,0 ;Manned
  108. MODEM_SETUP2    DB    "ATE0 S12=40 Q1S0=2",CR,0 ;Unattended
  109. MODEM_SETUP3    DB    "AT&C1",CR,0        ;Enable DCD on 2400 baud modem
  110. MODEM_SETUP4    DB    "ATW0X4&Q5&K3L0",CR,0    ;for 9600 baud modems
  111. MODEM_HANGUP    DB    "ATH0",CR,0
  112. MODEM_ESCAPE    DB    "+++",0
  113. PASS_MESSAGE    DB    "Enter password:",0    ;Enter password message
  114. PASSWORD_BUFFER DB    20 DUP(?)
  115. BAD_PASSWORD    DB    ?            ;0=No, don't send exit code
  116.                         ;1=Yes, 3 bad, so send code
  117. CONFIG:        ;The following parameters must remain in order to support
  118.         ; the setup program.
  119. MANNED_FLAG    DB    0            ;0=Operate in unattended mode
  120.                         ;1=Operate in manned mode
  121. COMM_FLAG    DB    0            ;0=Use comm1
  122.                         ;1=Use comm2
  123.                         ;2=Use comm3
  124.                         ;3=Use comm4
  125. COMM_PORT3    DW    03E8H            ;Port address for COMM 3
  126. COMM_PORT4    DW    02E8H            ;Port address for COMM 4
  127. COMM3_INT    DB    4            ;Interrupt for com1 and 3
  128. COMM4_INT    DB    3            ;Interrupt for com2 and 4
  129. SPEED_FLAG    DB    0            ;0=Use 1200 baud
  130.                         ;1=Use 2400 baud
  131.                         ;2=Use 4800 baud
  132.                         ;3=Use 9600 baud
  133.                         ;4=Use 19200 baud
  134.                         ;5=Use 38400 baud
  135. DESNOW_FLAG    DB    0            ;0=Do not use desnow code
  136.                         ;1=Use desnow code
  137. NULL_MODEM    DB    0            ;0=Using a modem
  138.                         ;1=Using a null modem cable
  139. SMILE_FLAG    DB    0            ;0=Disable corner smile face
  140.                         ;1=Enable corner smile face
  141. CLEAR_CODE    DB    0,2EH            ; alt-c, clear code
  142. EXIT_CODE    DB    0,45D            ; alt-x, code to exit program
  143. SHELL_CODE    DB    0,1FH            ;alt-s, shell to DOS code
  144. TRANSFER_CODE    DB    0,20D            ;alt-t, file transfer code
  145. PASSWORD_SIZE    DW    EXTRA_PW_SPACE-PASSWORD
  146. PASSWORD    DB    "PC MAGAZINE"
  147. EXTRA_PW_SPACE    DB    20-(EXTRA_PW_SPACE-PASSWORD) DUP(?)
  148. MODEM_SETUP5    DB    30 DUP(0);        ;Extra modem setup string
  149. TONE_DIAL    DB    "ATDT",0        ;Tone dial command
  150.  
  151. ;======================================================================
  152. ;  Interrupt handlers.  Interrupt 8 is used in unattended mode only.
  153. ;  The communications interrupt is used in both modes.
  154. ;======================================================================
  155. ;----------------------------------------------------------------------
  156. ;  Interrupt 8 handling routine.  If program is already active do not run.
  157. ;  Run connect unattended if not connected, otherwise run unattended.
  158. ;----------------------------------------------------------------------
  159. INT8        PROC    NEAR
  160.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  161.         PUSH    DS            ;Save data segment
  162.         PUSH    CS            ;Set data segment to code seg
  163.         POP    DS
  164.         PUSHF                ;Call old int 8
  165.         CALL    DWORD PTR OLDINT_8
  166. I8_10:
  167.         CLI                ;Disable interrupts
  168.         CMP    BYTE PTR SLEEP_FLAG,1    ;If another program has control
  169.         JZ    I8_EXIT         ;then exit
  170.         CMP    BYTE PTR ACT_FLAG,0    ;Check for program active
  171.         JNZ    I8_EXIT            ;Exit if progam is active
  172.         INC    BYTE PTR ACT_FLAG    ;Set program active flag
  173.         STI                ;Enable interrupts
  174.         CALL    SET_STACK        ;Create stack & save registers
  175.         CMP    BYTE PTR CONNECT_FLAG,0 ;Connected to manned?
  176.         JNZ    I8_20            ;Yes, then run unattended
  177.         CALL    CONNECT_UNATTENDED    ;No, check for connection
  178.         JMP    I8_30
  179. I8_20:
  180.         CALL    UNATTENDED        ;Run unattended
  181. I8_30:
  182.         CALL    RESET_STACK        ;Restore registers & stack
  183.         DEC    BYTE PTR ACT_FLAG    ;Clear program active flag
  184. I8_EXIT:
  185.         STI                ;Enable interrupts
  186.         POP    DS            ;Restore data segment
  187.         IRET
  188. INT8        ENDP
  189.  
  190. ;----------------------------------------------------------------------
  191. ;  Interrupt 21 handling routine.  If another program, zcopy, changes 
  192. ;  the comm interrupt, go to sleep by setting the sleep flag.  When the 
  193. ;  comm interrupt vector returns, WAKE UP!
  194. ;----------------------------------------------------------------------
  195. INT21        PROC    FAR
  196.         PUSHF                ;save registers
  197.         PUSH    AX
  198.         PUSH    BX
  199.         CMP    AX,WORD PTR CS:SET_VEC    ;setting comm int. vector?
  200.         JZ    I21_20            ;yes
  201. I21_10:
  202.         POP    BX            ;no, restore registers
  203.         POP    AX
  204.         POPF
  205.         JMP    DWORD PTR CS:OLDINT_21    ;execute original DOS int
  206. I21_20:
  207.         MOV    AX,CS            ;is new code segment
  208.         MOV    BX,DS            ; the same as pcremote
  209.         CMP    AX,BX
  210.         JNZ    I21_30            ;no, then go to sleep
  211.         CMP    DX,OFFSET CS:INT_COMM    ;is it my comm interrupt vec?
  212.         JZ    I21_40            ;yes, wake up
  213. I21_30:
  214.         MOV    BYTE PTR CS:SLEEP_FLAG,1  ;I'm getting sleeeeepy
  215.         JMP    I21_10
  216. I21_40:
  217.         POP    BX            ;restore registers
  218.         POP    AX
  219.         STI                ;enable interrupts
  220.         CALL    DWORD PTR CS:OLDINT_21    ;execute original DOS int vec
  221.         CLI                ;disable interrupts
  222.         CALL    CLEAR_VIDEO        ;clear the screen
  223.         MOV    BYTE PTR CS:SLEEP_FLAG,00  ;WAKE UP!
  224.         PUSH    DX
  225.         PUSH    AX
  226.         PUSH    DS            ;Save data segment
  227.         PUSH    CS            ;Set data segment to code seg.
  228.         POP    DS
  229.         CALL    INIT_SERIAL        ;Re-initialize serial port
  230.         CALL    CLEAR_OUTBUFF        ;Clear buffers because ZCOPY
  231.         CALL    CLEAR_INBUFF        ; sent hex 02's to sync systems
  232.         POP    DS            ;Restore the data segment
  233.         POP    AX            ;Restore registers
  234.         POP    DX
  235.         STI                ;Enable interrupts
  236.         RET    2            ;Return to calling program
  237. INT21        ENDP
  238.  
  239. ;---------------------------------------------------------------------
  240. ;  Clear the video copy to force a new screen to be tranferred to 
  241. ;  remote system
  242. ;---------------------------------------------------------------------
  243. CLEAR_VIDEO:
  244.         PUSH    CX            ;Store necessary registers
  245.         PUSH    DI
  246.         PUSH    ES
  247.         PUSHF
  248.         CLD                ;Direction = forward
  249.         PUSH    CS            ;Push CS so ES can now
  250.         POP    ES            ; point at it .. ES->CS
  251.         MOV    DI,WORD PTR VIDEO_COPY    ;ES:DI->Video copy
  252.         MOV    AX,720H            ;AL=SPACE,AH=Normal attribute 
  253.         MOV    CX,2000D        ;Clear entire video copy
  254.         REP    STOSW            ;Store char and attribute
  255.         MOV    CURSOR_POSITION,0FFFFH    ;Reset cursor to be updated
  256.         POPF                ;Restore registers
  257.         POP    ES    
  258.         POP    DI
  259.         POP    CX
  260.         RET
  261.  
  262. ;----------------------------------------------------------------------
  263. ;  Interrupt handling routine for communications interrupt.  Provides
  264. ;  interrupt driven I/O.  Transmit or receive a character.
  265. ;----------------------------------------------------------------------
  266. INT_COMM    PROC    NEAR
  267.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  268.         PUSH    DS            ;Save data segment
  269.         PUSH    DX            ;Save registers
  270.         PUSH    BX
  271.         PUSH    AX
  272.         PUSH    CS            ;Set data segment to code seg.
  273.         POP    DS
  274.         MOV    DX,COMM_PORT        ;Get port base address
  275.         INC    DX            ;Point to int. id reg.
  276.         INC    DX
  277.         IN    AL,DX            ;Get the interrupt id byte
  278. IC_10:
  279.         CMP    AL,2            ;Transmit empty int?
  280.         JZ    IC_40            ;Yes transmit a byte
  281. ;
  282. ;    received data, get it and store in buffer
  283. ;
  284.         DEC    DX            ;Port base address
  285.         DEC    DX
  286.         IN    AL,DX            ;Get data from receive register
  287.         MOV    BX,IN_BUFF_TAIL        ;Get the buffer tail pointer
  288.         MOV    [BX],AL         ;Store the data in buffer
  289.         INC    BX            ;Point to next data storage
  290.         CMP    IN_BUFF_END,BX        ;Beyond end of buffer area?
  291.         JNE    IC_20            ;No, then don't reset
  292.         MOV    BX,IN_BUFF_BEGIN    ;Yes, reset to buffer begin
  293. IC_20:
  294.         CMP    BX,IN_BUFF_HEAD        ;Test for buffer full
  295.         JE    IC_30             ;If so,don't change ptr ,sorry
  296.         MOV    IN_BUFF_TAIL,BX        ;Save new tail pointer
  297. IC_30:
  298.         JMP    IC_70
  299. ;
  300. ;    transmit buffer empty, send a byte
  301. ;
  302. IC_40:
  303.         DEC    DX            ;Port base address
  304.         DEC    DX
  305.         MOV    BX,OUT_BUFF_HEAD    ;Get the buffer head pointer
  306.         CMP    BX,OUT_BUFF_TAIL    ;Test for data in buffer
  307.         JE    IC_60             ;If the same, no data so exit
  308.         MOV    AL,[BX]         ;Get the data
  309.         INC    BX            ;Point to next data in buffer
  310.         CMP    OUT_BUFF_END,BX        ;Beyond end of buffer area?
  311.         JNE    IC_50            ;No, then don't reset
  312.         MOV    BX,OUT_BUFF_BEGIN    ;Yes, reset to buffer begin
  313. IC_50:
  314.         MOV    OUT_BUFF_HEAD,BX     ;Save new head pointer
  315.         OUT    DX,AL            ;Send the data out the port
  316.         JMP    IC_70            ;Check for request pending
  317. IC_60:
  318.         MOV    BYTE PTR COMM_INT_STA,0    ;Reset transmitting data flag
  319. IC_70:
  320.         INC    DX            ;Point to int. id reg.
  321.         INC    DX
  322.         IN    AL,DX            ;Get the interrupt id byte
  323.         TEST    AL,1            ;Request pending?
  324.         JZ    IC_10            ;Yes, then process
  325. IC_EXIT:
  326.         MOV    AL,20H            ;Reset 8259
  327.         OUT    20H,AL
  328.         STI                ;Enable interrupts
  329.         POP    AX            ;Restore registers
  330.         POP    BX
  331.         POP    DX
  332.         POP    DS            ;Restore data segment
  333.         IRET
  334. INT_COMM    ENDP
  335.  
  336. ;----------------------------------------------------------------------
  337. ;  Create stack area and save all registers.
  338. ;----------------------------------------------------------------------
  339. SET_STACK    PROC    NEAR
  340.         ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  341.         MOV    TEMP_REG,BX        ;Save BX
  342.         POP    BX            ;Save the return address
  343.         PUSH    AX            ;Save AX
  344. ;
  345. ;    make my own stack
  346. ;
  347.         CLI                ;Disable interrupts
  348.         MOV    AX,SS            ;Put old stack segment in AX
  349.         MOV    OLD_SS,AX        ;And save it
  350.         MOV    AX,SP            ;Put old stack pointer in AX
  351.         MOV    OLD_SP,AX        ;And save it
  352.         MOV    AX,CS            ;Get current segment
  353.         MOV    SS,AX            ;And put into stack segment
  354.         MOV    AX,STACK_TOP         ;Get top of stack address
  355.         MOV    SP,AX            ;And put into stack pointer
  356.         STI                ;Enable interrupts
  357. ;
  358. ;    save all the registers on the stack
  359. ;
  360.         PUSH    CX
  361.         PUSH    DX
  362.         PUSH    SI
  363.         PUSH    DI
  364.         PUSH    DS
  365.         PUSH    ES
  366.         PUSH    BP
  367.         MOV    AX,CS            ;Get code segment
  368.         MOV    DS,AX            ;Set data segment to code seg
  369.         MOV    ES,AX            ;Set extra seg to code seg
  370.         PUSH    BX            ;Restore return address
  371.         RET
  372. SET_STACK    ENDP
  373.  
  374. ;----------------------------------------------------------------------
  375. ;  Restore all registers and reset stack
  376. ;----------------------------------------------------------------------
  377. RESET_STACK    PROC    NEAR
  378.         ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  379.         POP    BX            ;Save return address
  380. ;
  381. ;    restore the registers
  382. ;
  383.         POP    BP            ;Restore the registers
  384.         POP    ES
  385.         POP    DS
  386.         POP    DI
  387.         POP    SI
  388.         POP    DX
  389.         POP    CX
  390. ;
  391. ;    restore the original stack
  392. ;
  393.         CLI                ;Disable interrupts
  394.         MOV    AX,OLD_SP        ;Get old stack pointer
  395.         MOV    SP,AX            ;And restore it
  396.         MOV    AX,OLD_SS        ;Get old stack segment
  397.         MOV    SS,AX            ;And restore it
  398.         STI                ;Enable interrupts
  399.         POP    AX            ;Restore AX
  400.         PUSH    BX            ;Put return add back on stack
  401.         MOV    BX,TEMP_REG        ;Restore BX
  402.         RET
  403. RESET_STACK    ENDP
  404.  
  405. ;======================================================================
  406. ;  The unattended routine will execute the connect routine to establish
  407. ;  a connection with the manned system.  Once connected it will execute 
  408. ;  the unattended routine to process incoming data and send any changed
  409. ;  video data to the manned system.
  410. ;======================================================================
  411.  
  412. ;----------------------------------------------------------------------
  413. ;  CONNECT_UNATTENDED - Check for ring codes, answer the phone and check
  414. ;  the password.  If correct, set connected flag.
  415. ;----------------------------------------------------------------------
  416. CONNECT_UNATTENDED PROC    NEAR
  417.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  418.         MOV    BP,SP            ;Save stack pointer for exit
  419.         XOR    AH,AH            ;Use input buffer
  420.         MOV    CX,10D            ;Number of char to check for CR
  421.         MOV    BYTE PTR CR_COUNT,5    ;Number of matches required
  422. CU_10:
  423.         CALL    GET_BUFF_DATA        ;Try to get data from buffer
  424.         JC    CU_20            ;If data, check for CR code
  425.         JMP    CU_40            ;else exit, try another speed
  426. CU_20:
  427.         CMP    AL,CR            ;Check for CR code
  428.         JNZ    CU_30            ;No so skip over
  429.         MOV    BYTE PTR SPEED_COUNT,19    ;it's a CR, so speed is correct
  430.         DEC    BYTE PTR CR_COUNT    ;Found a match dec count
  431.         JZ    CU_70            ;5 out of ten then null connect
  432. CU_30:
  433.         LOOP    CU_10            ;Keep trying
  434. CU_40:
  435.         DEC    BYTE PTR SPEED_COUNT
  436.         JZ    CU_50
  437.         JMP    CU_EXIT
  438. CU_50:
  439.         DEC    BYTE PTR CURRENT_SPEED    ;Try a slower speed
  440.         CMP    BYTE PTR CURRENT_SPEED,0FFH ;Out of speeds?
  441.         JNZ    CU_60            ;No
  442.         MOV    AL,BYTE PTR SPEED_FLAG    ;Ran out of speeds, reset
  443.         MOV    BYTE PTR CURRENT_SPEED,AL ; to starting speed
  444. CU_60:
  445.         MOV    BYTE PTR SPEED_COUNT,19    ;reset tick counter
  446.         MOV    AL,BYTE PTR CURRENT_SPEED ;set the slower speed
  447.         CALL    SET_BAUD_RATE
  448.         CALL    CLEAR_INBUFF        ;Empty the input buffer
  449.         JMP    CU_EXIT            ;No 5 out of 10, exit
  450. CU_70:
  451.         MOV    BYTE PTR CONNECT_FLAG,1 ;Set connect flag
  452.         MOV    CX,3            ;3 tries to enter password
  453. CU_80:
  454.         MOV    SI,OFFSET PASS_MESSAGE    ;Point to enter password mess.
  455.         CALL    LOAD_ZSTRING        ;Load it into output buffer
  456.         CALL    GET_PASSWORD        ;Get the password
  457.         CALL    CHECK_PASSWORD        ;Check the password sent
  458.         JZ    CU_90             ;Jump if correct
  459.         LOOP    CU_80            ;Keep trying
  460.         MOV    AL,1            ;Use set up string 2
  461.         MOV    BYTE PTR BAD_PASSWORD,1D ;Send exit code
  462.         CALL    RESET_MODEM        ;Hangup and reset modem
  463.         JMP    CU_EXIT            ;Done, so exit
  464. CU_90:
  465.         MOV    AH,1            ;Use output buffer
  466.         XOR    AL,AL            ;Sync byte to send
  467.         MOV    CX,5            ;Send 5 of them
  468. CU_100:
  469.         CALL    PUT_BUFF_DATA        ;Send them
  470.         LOOP    CU_100
  471. ;
  472. ; Notify remote computer the value of host's COMM_FLAG switch.  This allows
  473. ; the remote computer to properly send the ZCOPY command line to the host.
  474. ;
  475.         MOV    AH,1            ;Use output buffer
  476.         MOV    AL,BYTE PTR COMM_FLAG    ;Send host's comm port
  477.         INC    AL            ;Bump AL so sent byte will be
  478.                         ; in range from 1 thru 4.
  479.         MOV    CX,10D            ;Send 10 of them
  480. CU_110:                 
  481.         CALL    PUT_BUFF_DATA        ;Send Host Comm Port
  482.         LOOP    CU_110            ;Sent 10 ?
  483.         XOR    AL,AL            ;Sync byte to send
  484.         MOV    CX,5D            ;Send 5 of them
  485. CU_120:                    
  486.         CALL    PUT_BUFF_DATA        ;Send sync byte
  487.         LOOP    CU_120            ;Sent 5 ?
  488. CU_EXIT:
  489.         RET
  490. CONNECT_UNATTENDED ENDP
  491.  
  492. ;----------------------------------------------------------------------
  493. ;  Get the password from the manned system
  494. ;  Input - Nothing
  495. ;  Output - Password buffer contains password from manned system
  496. ;  Changes - DI, AX
  497. ;----------------------------------------------------------------------
  498. GET_PASSWORD    PROC    NEAR
  499.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  500.         PUSH    CX              ;Save register
  501.         MOV    DI,OFFSET PASSWORD_BUFFER ;Point to password buffer
  502.         MOV    CX,20D              ;Zero buffer to clear previous
  503.         XOR    AL,AL              ; password
  504.         CLD
  505.         REP    STOSB
  506.         MOV    DI,OFFSET PASSWORD_BUFFER ;Pointer to buffer
  507.         MOV    CX,20D              ;Maximum password size
  508. GP_10:
  509.         CALL    CHECK_CARRIER        ;Check for carrier loss
  510.         JNZ    GP_20
  511.         JMP    IP_90            ;Carrier loss, reset and exit
  512. GP_20:
  513.         CALL    INPUT_PROCESSING    ;Get data & put in keybd buffer
  514.         CALL    GET_KEYSTROKE        ;Check for keystroke
  515.         JZ    GP_10            ;None, so wait
  516.         CMP    AL,60H            ;Check for lower case
  517.         JL    GP_30            ;No then leave it alone
  518.         AND    AL,5FH            ;Convert to upper case
  519. GP_30:
  520.         CMP    AL,CR            ;If it is a CR then exit
  521.         JZ    GP_EXIT
  522.         CMP    AL,BS            ;Is it a back space?
  523.         JNZ    GP_40            ;No, so save it
  524.         INC    CX              ;Resetcounter for BS
  525.         CMP    DI,OFFSET PASSWORD_BUFFER ;Already at start of buffer?
  526.         JZ    GP_60              ;Yes, then don't backspace
  527.         DEC    DI            ;Backspace buffer pointer
  528.         MOV    BYTE PTR [DI],0        ; and null the data
  529.         JMP    GP_50
  530. GP_40:
  531.         CLD                ;Forward
  532.         STOSB                ;Save the character
  533.         MOV    AL,'*'            ;Echo character
  534. GP_50:
  535.         MOV    AH,1            ;Use output buffer
  536.         CALL    PUT_BUFF_DATA        ; and store the character
  537. GP_60:
  538.         LOOP    GP_10            ;Receive up to CX characters
  539. GP_EXIT:
  540.         POP    CX            ;Restore register
  541.         RET
  542. GET_PASSWORD    ENDP
  543.  
  544. ;----------------------------------------------------------------------
  545. ;  Check the password in the buffer with correct password
  546. ;  Input - Nothing
  547. ;  Output - Zero set - correct password
  548. ;        Zero reset - Wrong password
  549. ;  Changes - SI, DI
  550. ;----------------------------------------------------------------------
  551. CHECK_PASSWORD    PROC    NEAR
  552.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  553.         PUSH    CX              ;Save register
  554.         MOV    SI,OFFSET PASSWORD_BUFFER ;Pointer to buffer
  555.         MOV    DI,OFFSET PASSWORD      ;Pointer to password
  556.         MOV    CX,PASSWORD_SIZE    ;Number of compares to make
  557.         CLD                ;Compare forward
  558.         REPZ    CMPSB            ;Repeat while passwords match
  559.         POP    CX            ;Restore register
  560.         RET
  561. CHECK_PASSWORD    ENDP
  562.  
  563. ;----------------------------------------------------------------------
  564. ;  UNATTENDED - Process incoming data and check for changes in video 
  565. ;  data, format and send to manned system.  Maintains 18 or less characters
  566. ;  in output buffer, ensures maximum throughput.
  567. ;----------------------------------------------------------------------
  568. UNATTENDED    PROC    NEAR
  569.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  570.         MOV    BP,SP            ;Save stack pointer for exit
  571.         CALL    INPUT_PROCESSING    ;Process any buffered data
  572. ;
  573. ;    Check for a change in the cursor position
  574. ;
  575.         PUSH    ES
  576.         MOV    AX,40H            ;Set ES to BIOS data segment
  577.         MOV    ES,AX
  578.         MOV    BX,ES:[50H]        ;Get current cursor position
  579.         CMP    BX,CURSOR_POSITION    ;Compare with copy
  580.         JZ    UA_10            ;No change, skip
  581.         MOV    CURSOR_POSITION,BX    ;Save new cursor position
  582.         MOV    AL,0D2H         ;Sync bits, set position
  583.         MOV    AH,1            ;Use output buffer
  584.         CALL    PUT_BUFF_DATA        ;Send sync byte
  585.         MOV    AL,BL            ;Low byte
  586.         CALL    PUT_BUFF_DATA
  587.         MOV    AL,BH            ;High byte
  588.         CALL    PUT_BUFF_DATA
  589. UA_10:
  590.         POP    ES                      ;Restore ES
  591.         CMP    BYTE PTR SMILE_FLAG,0    ;Smile face enabled ?
  592.         JE    UA_20            ;No, skip smile face coding
  593. ;
  594. ; Redisplay the smile face in upper right corner
  595. ;
  596.         PUSH    ES            ;Store ES
  597.         MOV    AX,VIDEO_SEGMENT    ;AX = Video Segment
  598.         MOV    ES,AX            ;ES = Video Segment
  599.         MOV    DI,158D         ;DI-> Upper right corner
  600.         MOV    AL,01H            ;Smiley Face code
  601.         CALL    PUT_VIDEO_DATA        ;Write Video RAM
  602.         POP    ES            ;Restore ES
  603. UA_20:
  604.         MOV    VID_RAM_OFFSET,0    ;Start at address 0
  605.         MOV    BYTE PTR BLOCK_COUNT,0    ;Reset block counter
  606. ;
  607. ; Check the output buffer and keep it full enough so it's busy till
  608. ; next timer tick.
  609. ;
  610. UA_30:
  611.         MOV    AX,7            ;1200 baud, at least 7 bytes
  612.         MOV    CL,BYTE PTR CURRENT_SPEED ;the speed decides the size
  613.         SHL    AX,CL            ;larger for faster baud
  614.         MOV    CX,AX            ;at least this many bytes
  615.         CLI
  616.         MOV    AX,OUT_BUFF_HEAD    ;Get the head pointer
  617.         MOV    BX,OUT_BUFF_TAIL    ;Get the tail pointer
  618.         STI
  619. UA_40:
  620.         CMP    AX,BX            ;Less than bytes in buffer
  621.         JZ    UA_60            ;Yes, check the video data
  622.         INC    AX            ;Increment head pointer
  623.         CMP    OUT_BUFF_END,AX        ;Beyond end of buffer area?
  624.         JNE    UA_50            ;No, then don't reset
  625.         MOV    AX,OUT_BUFF_BEGIN    ;Yes, reset to buffer begin
  626. UA_50:
  627.         LOOP    UA_40            ;Check all the bytes
  628.         JMP    UA_EXIT            ;More than allowed, exit
  629. ;
  630. ;    compare the video copy with the video ram
  631. ;
  632. UA_60:
  633.         PUSH    DS            ;Save data segment
  634.         MOV    SI,VID_RAM_OFFSET    ;Get the current offset
  635.         MOV    DI,TEMP_VIDEO_PTR    ;Dest. ES:DI temp video buffer
  636.         MOV    AX,VIDEO_SEGMENT    ;Get video Segment register
  637.         MOV    DS,AX            ;Source DS:SI video RAM
  638. ;
  639. ;    transfer block_size words of data from video RAM to the temp buffer
  640. ;
  641.         MOV    CX,BLOCK_SIZE        ;Get count of words to transfer
  642.         CLD
  643.         CMP    BYTE PTR CS:DESNOW_FLAG,0 ;Check desnow flag
  644.         JZ    UA_90
  645.         SAL    CX,1            ;Convert words to bytes
  646.         MOV    DX,3DAH            ;CGA status port
  647. UA_70:
  648.         IN    AL,DX            ;Get status byte
  649.         TEST    AL,1            ;Test display enable
  650.         JNZ    UA_70            ;If in Hor. sync then wait
  651.         CLI                ;Disable interrupts
  652. UA_80:
  653.         IN    AL,DX            ;Get status byte
  654.         TEST    AL,1            ;Test display enable
  655.         JZ    UA_80            ;Wait for Hor. sync
  656.         MOVSB                ;Transfer one byte
  657.         STI                ;Enable interrupts
  658.         LOOP    UA_70            ;Transfer block size words
  659.         JMP    UA_100
  660. UA_90:
  661.         REP    MOVSW
  662. UA_100:
  663.         POP    DS            ;Restore data segment
  664. ;
  665. ;    compare the block from video RAM with the video copy
  666. ;
  667.         MOV    CX,BLOCK_SIZEX2     ;Number of words to compare
  668.         MOV    SI,TEMP_VIDEO_PTR    ;Point to block of video data
  669.         MOV    DI,VIDEO_COPY        ;Point to video copy
  670.         ADD    DI,VID_RAM_OFFSET    ;Adjust for current block
  671.         REPE    CMPSB            ;Compare while equal
  672.         JNE    UA_110            ;No match, format & send block
  673.         MOV    AX,VID_RAM_OFFSET    ;Get current block pointer
  674.         ADD    AX,BLOCK_SIZEX2     ;Point to next block
  675.         MOV    VID_RAM_OFFSET,AX    ;And save the pointer
  676.         INC    BYTE PTR BLOCK_COUNT    ;Increment current block count
  677.         CMP    AX,4000D        ;Check for end of video RAM
  678.         JNZ    UA_60            ;No, keep checking the RAM
  679.         JMP    UA_EXIT            ;then exit
  680. ;
  681. ;    data doesn't match, format and send to manned system
  682. ;
  683. UA_110:
  684.         INC    CX            ;Adjust count
  685.         AND    CX,1            ;LSB indicates char or attr.
  686.         CALL    TRANSFER_BLOCK        ;Prepare to send block of data
  687.         JMP    UA_30            ;Again, till buffer is full
  688. UA_EXIT:
  689.         RET
  690. UNATTENDED    ENDP
  691.  
  692. ;----------------------------------------------------------------------
  693. ;  Get data from the unattended input buffer and process
  694. ;  Input - Nothing
  695. ;  Output - Keyboard buffer or shift status is updated
  696. ;  Changes - Nothing
  697. ;----------------------------------------------------------------------
  698. INPUT_PROCESSING PROC     NEAR
  699.         PUSH    AX            ;Save register
  700.         PUSH    DX
  701.         PUSH    ES
  702.         MOV    AX,40H            ;Set ES to BIOS data area
  703.         MOV    ES,AX
  704. IP_10:
  705.         CMP    BYTE PTR CONNECT_FLAG,0 ;Are we connected
  706.         JZ    IP_20            ;No, don't check carrier
  707.         CALL    CHECK_CARRIER        ;Yes check for carrier loss
  708.         JZ    IP_90            ;Carrier loss, reset and exit
  709. ;
  710. ;  make sure there is room in the keyboard buffer for a keystroke
  711. ;
  712. IP_20:
  713.         CLI                ;Don't allow interrupts
  714.         MOV    AX,ES:[1CH]        ;Get the buffer tail pointer
  715.         INC    AX            ;Point to next data storage
  716.         INC    AX
  717.         CMP    AX,3EH            ;Beyond end of buffer area?
  718.         JNE    IP_30            ;No, then don't reset
  719.         MOV    AX,1EH            ;Yes, reset to buffer begin
  720. IP_30:
  721.         CMP    AX,ES:[1AH]        ;Test for buffer full
  722.         JE    IP_40             ;If the same, don't process key
  723.         STI
  724.         JMP    IP_50            ;Process incoming keystrokes
  725. IP_40:
  726.         STI                ;Enable interrupts
  727.         JMP    IP_EXIT            ;Exit the routine
  728. IP_50:
  729.         MOV    AH,0            ;Use input buffer
  730.         CALL    GET_BUFF_DATA        ;Get a byte of data
  731.         JC    IP_60            ;If data then process
  732.         JMP    IP_EXIT            ;Otherwise exit
  733. ;
  734. ;    Check to see if expecting ASCII data
  735. ;
  736. IP_60:
  737.         CMP    ASCII_FLAG,0        ;Check ASCII flag
  738.         JNZ    IP_70            ;
  739.         JMP    IP_120            ; 0=not expecting data here
  740. IP_70:
  741.         CMP    ASCII_FLAG,1        ;Check for received 1st byte
  742.         JNZ    IP_80            ;Jump if second byte
  743.         MOV    KEY_ONE,AL        ;Save scan code, byte one
  744.         INC    BYTE PTR ASCII_FLAG    ;Indicate receiving one byte
  745.         JMP    IP_10            ;Process next byte
  746. IP_80:
  747.         MOV    KEY_TWO,AL        ;Save ASCII code, byte two
  748.         MOV    AL,KEY_ONE        ;Get ASCII code
  749.         MOV    AH,KEY_TWO        ;Get scan code
  750.         CMP    AX,WORD PTR EXIT_CODE    ;Check for exit code
  751.         JNZ    IP_100            ;No,then continue processing
  752. IP_90:                        ;Otherwise reset connect & exit
  753.         CMP    BYTE PTR SMILE_FLAG,0    ;Smile flag set ?
  754.         JE    IP_95            ;No, skip resetting smile face
  755.         PUSH    AX            ;Store AX
  756.         PUSH    ES            ;Store ES
  757.         PUSH    DI            ;Store DI
  758.         MOV    AX,VIDEO_SEGMENT    ;AX = VIDEO_SEGMENT
  759.         MOV    ES,AX            ;ES = VIDEO_SEGMENT
  760.         MOV    DI,158D         ;Bump DI 79 chars
  761.         MOV    AL,SPACE        ;Blank space
  762.         CALL    PUT_VIDEO_DATA        ;Write Video RAM
  763.         POP    DI            ;Restore DI
  764.         POP    ES            ;Restore ES
  765.         POP    AX            ;Restore AX
  766. IP_95:
  767.         CALL    CLEAR_INBUFF        ;Clear input buffer
  768.         CALL    CLEAR_OUTBUFF        ;Clear output buffer
  769.         MOV    BYTE PTR COMM_INT_STA,0    ;Reset transmitting data flag
  770.         CALL    IU_10            ;reinit and reset modem
  771.         CLI                ;Disable interrupts
  772.         MOV    BYTE PTR CONNECT_FLAG,0 ;Reset the connect flag
  773.         MOV    BYTE PTR ASCII_FLAG,0    ;Reset ASCII flag
  774.         MOV    BYTE PTR SHIFT_FLAG,0    ;Reset shift flag
  775.         MOV    BYTE PTR ES:[17H],0    ;Reset any shift status
  776.         MOV    SP,BP            ;Clean the stack
  777.         RET                 ;And exit unattended routine
  778. IP_100:
  779.         CMP    AX,WORD PTR CLEAR_CODE    ;Clear code received
  780.         JNZ    IP_110            ;No... skip clear code coding
  781.         CALL    CLEAR_VIDEO        ;Rewrite screen
  782.         MOV    BYTE PTR ASCII_FLAG,0    ;Reset ASCII flag
  783.         JMP    IP_10            ;Get next character
  784. IP_110:                        ;
  785.         CALL    PUT_KEY_DATA        ;And stuff in keyboard buffer
  786.         MOV    BYTE PTR ASCII_FLAG,0    ;Reset ASCII flag for next data
  787.         JMP    IP_10            ;Process next byte
  788. ;
  789. ;    Check to see if expecting shift data
  790. ;
  791. IP_120:
  792.         CMP    BYTE PTR SHIFT_FLAG,0    ;Check shift flag
  793.         JZ    IP_130            ;0=not expecting data here
  794.         MOV    ES:[17H],AL        ;And save in shift status
  795.         MOV    BYTE PTR SHIFT_FLAG,0    ;Reset shift flag for next data
  796.         JMP    IP_10            ;Process next byte
  797. ;
  798. ;    Check to see if it's a sync byte
  799. ;
  800. IP_130:
  801.         CMP    AL,0FEH         ;Check for ASCII sync byte
  802.         JNZ    IP_140            ;If not then check for shift
  803.         INC    BYTE PTR ASCII_FLAG    ;Indicate received FEh
  804.         JMP    IP_10            ;Process next byte
  805. IP_140:
  806.         CMP    AL,0FDH         ;Check for shift sync byte
  807.         JNZ    IP_150            ;If not then throw away
  808.         INC    BYTE PTR SHIFT_FLAG    ;Indicate received FDh
  809. IP_150:
  810.         JMP    IP_10            ;Process till buffer empty
  811. IP_EXIT:
  812.         POP    ES            ;Restore registers
  813.         POP    DX
  814.         POP    AX
  815.         RET
  816. INPUT_PROCESSING ENDP
  817.  
  818. ;----------------------------------------------------------------------
  819. ;  Formats the data in temporary video buffer and puts it into the
  820. ;  output buffer
  821. ;  Input - CX=0 Transfer character data to output buffer
  822. ;       CX=1 Transfer attribute data to output buffer
  823. ;  Output - Nothing
  824. ;  Changes - AX, BX, CX, SI, DI
  825. ;----------------------------------------------------------------------
  826. TRANSFER_BLOCK    PROC    NEAR
  827.         PUSH    CX            ;Save the data type
  828. ;
  829. ; If the data is all the same only send it once, and set the repeat flag
  830. ;
  831.         MOV    SI,TEMP_VIDEO_PTR    ;Point
  832.         ADD    SI,CX            ;Adjust for char. or attr.
  833.         XOR    BL,BL            ;Initialize for non-repeating
  834.         MOV    CX,BLOCK_SIZE        ;Number of bytes to compare
  835.         MOV    AH,[SI]            ;Get the first byte in block
  836. TB_10:
  837.         LODSB                ;Get next byte from the block
  838.         INC    SI            ;Adjust for word
  839.         CMP    AH,AL            ;Verify all the same
  840.         LOOPZ    TB_10            ;For the entire block
  841.         JNZ    TB_20            ;Not the same, send block
  842.         MOV    BL,2            ;set repeat flag
  843. TB_20:
  844.         POP    CX            ;Restore data type
  845.         MOV    AL,0FCH            ;Start with base sync byte
  846.         OR    AL,CL            ;Include data type bit
  847.         OR    AL,BL            ;Include repeat bit
  848.         MOV    AH,1            ;Use output buffer
  849.         CALL    PUT_BUFF_DATA        ;Put sync byte in output buff.
  850.         MOV    AL,BLOCK_COUNT
  851.         MOV    AH,1            ;Use output buffer
  852.         CALL    PUT_BUFF_DATA        ;Send the block number
  853.         MOV    SI,TEMP_VIDEO_PTR    ;Point to block of video data
  854.         ADD    SI,CX            ;Adjust for char. or attr.
  855.         MOV    DI,VIDEO_COPY        ;Point to video copy
  856.         ADD    DI,VID_RAM_OFFSET    ;Adjust for block offset
  857.         ADD    DI,CX            ; and character or attribute
  858.         MOV    CX,BLOCK_SIZE        ;Number of bytes to send
  859.         CLD                ;Forward direction
  860. TB_30:
  861.         LODSW                ;Get the unmatched data
  862.         OR    BL,BL            ;Check the repeat flag
  863.         JNZ    TB_40            ;Don't send repeat data
  864.         MOV    AH,1            ;Use the output buffer
  865.         CALL    PUT_BUFF_DATA        ;Put the video data in out buff
  866. TB_40:
  867.         STOSB                ;Save video data in copy
  868.         INC    DI            ;Adjust for word offset
  869.         LOOP    TB_30            ;Send block size bytes of data
  870.         OR    BL,BL            ;If repeat data then send one
  871.         JZ    TB_50
  872.         MOV    AH,1
  873.         CALL    PUT_BUFF_DATA
  874. TB_50:
  875.         RET
  876. TRANSFER_BLOCK    ENDP
  877.  
  878. ;----------------------------------------------------------------------
  879. ;  Put a byte of data into the unattended keyboard buffer.
  880. ;  Input - AL contains ASCII to be put into buffer.
  881. ;       AH contains scan code to be put into buffer.
  882. ;  Output - Carry Set - Byte placed in buffer successfully
  883. ;        Carry Reset - Buffer full, byte not stored in buffer
  884. ;  Changes - Nothing
  885. ;----------------------------------------------------------------------
  886. PUT_KEY_DATA    PROC    NEAR
  887.         PUSH    BX            ;Save registers
  888.         PUSH    SI
  889.         PUSH    DI
  890.         MOV    SI,1AH            ;Point to keyboard head pointer
  891.         CLI                ;Don't allow interrupts
  892.         MOV    BX,ES:[1CH]        ;Get the buffer tail pointer
  893.         MOV    DI,BX            ;Save the tail pointer
  894.         INC    BX            ;Point to next data storage
  895.         INC    BX
  896.         CMP    BX,3EH            ;Beyond end of buffer area?
  897.         JNE    PK_10            ;No, then don't reset
  898.         MOV    BX,1EH            ;Yes, reset to buffer begin
  899. PK_10:
  900.         CMP    BX,ES:[1AH]        ;Test for buffer full
  901.         JE    PK_EXIT         ;If the same, don't save it
  902.                         ; exit, carry is already reset
  903.         MOV    ES:[DI],AX        ;Store the data in buffer
  904.         MOV    ES:[1CH],BX        ;Save new tail pointer
  905.         STC                ;Indicate data stored OK
  906. PK_EXIT:
  907.         POP    DI
  908.         POP    SI
  909.         POP    BX
  910.         STI                ;Enable interrupts
  911.         RET
  912. PUT_KEY_DATA   ENDP
  913.  
  914. ;======================================================================
  915. ;  COMMON ROUTINES - These routines are common to both the unattended
  916. ;  processing portion of the program and the manned processing portion.
  917. ;======================================================================
  918.  
  919. ;----------------------------------------------------------------------
  920. ; Store the video data in AL in the memory location pointed to by DI
  921. ; INPUT - AL video data, ES:DI video RAM destination
  922. ; OUTPUT - Nothing
  923. ; Changes - DI is incremented
  924. ;----------------------------------------------------------------------
  925. PUT_VIDEO_DATA    PROC    NEAR
  926.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  927. ;
  928. ; Check desnow flag, if set wait for horizontal sync to put in video RAM
  929. ;
  930.         PUSH    BX                ; Save Registers
  931.         PUSH    DX
  932.         CMP    BYTE PTR DESNOW_FLAG,0        ; Check Desnow flag
  933.         JZ    PV_30                ; No, skip over
  934.         CLD                    ; Forward
  935.         XCHG    AX,BX                ; Save video data
  936.         MOV    DX,3DAH             ; CGA status port
  937. PV_10:
  938.         IN    AL,DX                ; Get status byte
  939.         TEST    AL,1                ; Test display enable
  940.         JNZ    PV_10                ; If in Hor. sync, wait
  941. PV_20:
  942.         IN    AL,DX                ; Get status byte
  943.         TEST    AL,1                ; Test display enable
  944.         JZ    PV_20                ; Wait for Hor. sync
  945.         XCHG    AX,BX                ; Get video data
  946. PV_30:
  947.         STOSB                    ; Put into video RAM
  948.         POP    DX                ; Restore registers
  949.         POP    BX
  950.         RET
  951. PUT_VIDEO_DATA    ENDP
  952.  
  953. ;----------------------------------------------------------------------
  954. ;  Get a byte of data from a buffer.  Byte pointed to by head pointer is
  955. ;  is next data byte.  If head=tail, no data in buffer.
  956. ;  Input - AH - Buffer to use 0=Input buffer, 1=Output buffer.
  957. ;  Output - Carry Set - Byte from buffer is in AL
  958. ;        Carry Reset - No data in buffer
  959. ;  Changes - AL
  960. ;----------------------------------------------------------------------
  961. GET_BUFF_DATA    PROC    NEAR
  962.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  963.         PUSH    BX            ;Save registers
  964.         PUSH    SI
  965.         CMP    AH,0            ;Check which buffer to use
  966.         JNZ    GD_10            ;Jump for output buffer
  967.         MOV    SI,OFFSET IN_BUFF_HEAD    ;Point to input buffer
  968.         JMP    GD_20            ;Skip over out buffer
  969. GD_10:
  970.         MOV    SI,OFFSET OUT_BUFF_HEAD ;Point to output buffer
  971. GD_20:
  972.         CLI                ;Don't allow interrupts
  973.         MOV    BX,[SI]         ;Get the buffer head pointer
  974.         CMP    BX,2[SI]        ;Test for data in buffer
  975.         JE    GD_EXIT         ;If the same, no data so
  976.                         ; exit, carry is already reset
  977.         MOV    AL,[BX]         ;Get the data
  978.         INC    BX            ;Point to data in buffer
  979.         CMP    6[SI],BX        ;Beyond end of buffer area?
  980.         JNE    GD_30            ;No, then don't reset
  981.         MOV    BX,4[SI]        ;Yes, reset to buffer begin
  982. GD_30:
  983.         MOV    [SI],BX         ;Save new head pointer
  984.         STC                ;Indicate data is in AL
  985. GD_EXIT:
  986.         POP    SI            ;Restore registers
  987.         POP    BX
  988.         STI                ;Enable interrupts
  989.         RET
  990. GET_BUFF_DATA    ENDP
  991.  
  992. ;----------------------------------------------------------------------
  993. ;  Put a byte of data into a buffer.  Byte is stored at location
  994. ;  pointed to by tail pointer.
  995. ;  Input - AL contains data to be put into buffer.
  996. ;       AH - Buffer to use 0=Input buffer, 1=Output buffer
  997. ;  Output - Carry Set - byte placed in buffer successfully
  998. ;        Carry Reset - Buffer full, byte not stored in buffer
  999. ;  Changes - Nothing
  1000. ;----------------------------------------------------------------------
  1001. PUT_BUFF_DATA    PROC    NEAR
  1002.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1003.         PUSH    AX            ;Save registers
  1004.         PUSH    BX
  1005.         PUSH    DX
  1006.         PUSH    SI
  1007.         PUSH    DI
  1008.         PUSH    DS
  1009.         PUSH    CS            ;Set data segment to CS
  1010.         POP    DS
  1011.         CMP    AH,0            ;Check which buffer to use
  1012.         JNZ    PD_10            ;Jump for output buffer
  1013.         MOV    SI,OFFSET IN_BUFF_HEAD    ;Point to input buffer
  1014.         JMP    PD_20            ;Skip over out buffer
  1015. PD_10:
  1016.         MOV    SI,OFFSET OUT_BUFF_HEAD ;Point to output buffer
  1017. PD_20:
  1018.         CLI                ;Don't allow interrupts
  1019.         MOV    BX,2[SI]        ;Get the buffer tail pointer
  1020.         MOV    DI,BX            ;Save the tail pointer
  1021.         INC    BX            ;Point to next data storage
  1022.         CMP    6[SI],BX        ;Beyond end of buffer area?
  1023.         JNE    PD_30            ;No, then don't reset
  1024.         MOV    BX,4[SI]        ;Yes, reset to buffer begin
  1025. PD_30:
  1026.         CMP    BX,[SI]         ;Test for buffer full
  1027.         JE    PD_40             ;If so, exit carry is reset
  1028.  
  1029.         MOV    [DI],AL         ;Store the data in buffer
  1030.         MOV    2[SI],BX        ;Save new tail pointer
  1031.         STC                ;Indicate data stored ok
  1032. PD_40:
  1033.         PUSHF                ;Save the flags
  1034.         CMP    BYTE PTR COMM_INT_STA,0    ;Transmit int. running?
  1035.         JNZ    PD_60            ;Yes, so exit
  1036.         MOV    AX,OUT_BUFF_HEAD    ;Is data in output buffer
  1037.         CMP    AX,OUT_BUFF_TAIL
  1038.         JZ    PD_60            ;No, so exit
  1039.         MOV    BYTE PTR COMM_INT_STA,1    ;Set transmitting data flag
  1040.         MOV    DX,COMM_PORT        ;Get port base address
  1041.         ADD    DX,5            ;Line status register
  1042. PD_50:
  1043.         IN    AL,DX            ;Make sure holding reg. empty
  1044.         TEST    AL,00100000B        ;Test the hold reg empty flag
  1045.         JZ    PD_50            ;Loop if not empty
  1046.         SUB    DX,5            ;Port base register
  1047.         MOV    AH,1            ;Use the output buffer
  1048.         CALL    GET_BUFF_DATA        ;Get data from output buffer
  1049.         OUT    DX,AL            ;Send the data out the port
  1050. PD_60:
  1051.         STI                ;Enable interrupts
  1052.         POPF                ;Restore flags
  1053.         POP    DS            ;Restore registers
  1054.         POP    DI
  1055.         POP    SI
  1056.         POP    DX
  1057.         POP    BX
  1058.         POP    AX
  1059.         RET
  1060. PUT_BUFF_DATA    ENDP
  1061.  
  1062. ;----------------------------------------------------------------------
  1063. ;  Clear the input buffer
  1064. ;  Input - Nothing
  1065. ;  Output - Nothing
  1066. ;  Changes - Nothing
  1067. ;----------------------------------------------------------------------
  1068. CLEAR_INBUFF    PROC    NEAR
  1069.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1070.         PUSH    AX            ;Save register
  1071.         CLI                ;Disable interrupts
  1072.         MOV    AX,IN_BUFF_TAIL        ;Get buffer tail pointer
  1073.         MOV    IN_BUFF_HEAD,AX        ;Make head equal tail
  1074.         STI                ;Enable interrupts
  1075.         POP    AX
  1076.         RET
  1077. CLEAR_INBUFF    ENDP
  1078.  
  1079. ;----------------------------------------------------------------------
  1080. ;  Clear the output buffer
  1081. ;  Input - Nothing
  1082. ;  Output - Nothing
  1083. ;  Changes - Nothing
  1084. ;----------------------------------------------------------------------
  1085. CLEAR_OUTBUFF    PROC    NEAR
  1086.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1087.         PUSH    AX            ;Save register
  1088.         CLI                ;Disable interrupts
  1089.         MOV    AX,OUT_BUFF_TAIL    ;Get buffer tail pointer
  1090.         MOV    OUT_BUFF_HEAD,AX    ;Make head equal tail
  1091.         STI                ;Enable interrupts
  1092.         POP    AX
  1093.         RET
  1094. CLEAR_OUTBUFF    ENDP
  1095.  
  1096. ;----------------------------------------------------------------------
  1097. ;  Reset the modem and send the setup string to initialize
  1098. ;  Input - AL - 0 use setup string 1, 1 use setup string 2
  1099. ;  Output - Nothing
  1100. ;  Changes - Nothing
  1101. ;----------------------------------------------------------------------
  1102. RESET_MODEM    PROC    NEAR
  1103.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1104.         CMP    BYTE PTR NULL_MODEM,0    ;If null modem don't reset
  1105.         JZ    RM_10
  1106.         MOV    BYTE PTR CONNECT_FLAG,0 ;Reset connect flag
  1107. ;
  1108. ; After resetting connect flag, see if unattended and three bad passwords
  1109. ; received, if so send an exit code to the remote computer so that the
  1110. ; remote computer can exit to DOS.
  1111. ;
  1112.         CMP    BYTE PTR MANNED_FLAG,0    ;If host, then send exit code
  1113.         JNE    RM_5            ; to remote system to exit
  1114.         CMP    BYTE PTR BAD_PASSWORD,0 ;Three bad passwords ?
  1115.         JE    RM_5            ;No, skip sending exit code
  1116.         CALL    CLEAR_OUTBUFF        ;Clear out buff to insure room
  1117.         MOV    AX,WORD PTR EXIT_CODE    ;Set up AL and AH to send
  1118.         MOV    AL,AH            ; the exit code thru out buff.
  1119.         MOV    AH,1            ;Use output buffer
  1120.         CALL    PUT_BUFF_DATA        ;Send char (exit_code)
  1121. RM_5:                        ;
  1122.         JMP    RM_EXIT            ;and return to caller
  1123. RM_10:
  1124.         PUSH    SI            ;Save registers
  1125.         PUSH    DX
  1126.         PUSH    AX
  1127.         CMP    BYTE PTR CONNECT_FLAG,0 ;Is modem connected?
  1128.         JZ    RM_20            ;No then send setup only
  1129.         CALL    CLEAR_OUTBUFF        ;Empty the output buffer
  1130.         MOV    BYTE PTR CONNECT_FLAG,0 ;Reset connect flag
  1131.         MOV    AL,1            ;Wait a second for guard time
  1132.         CALL    DELAY
  1133.         MOV    SI,OFFSET MODEM_ESCAPE    ;Send modem escape code
  1134.         CALL    LOAD_ZSTRING
  1135.         MOV    AL,2            ;Wait
  1136.         CALL    DELAY
  1137.         MOV    SI,OFFSET MODEM_HANGUP    ;Send modem hangup code
  1138.         CALL    LOAD_ZSTRING
  1139.         MOV    AL,1            ;Wait for a second
  1140.         CALL    DELAY
  1141. RM_20:
  1142.         MOV    AL,SPEED_FLAG        ;Get speed flag
  1143.         MOV    BYTE PTR CURRENT_SPEED,AL ;Save as next starting speed
  1144.         CALL    SET_BAUD_RATE
  1145.         MOV    BYTE PTR SPEED_COUNT,19
  1146.         MOV    SI,OFFSET MODEM_ATTENTION ;Point to modem attention
  1147.         CALL    LOAD_ZSTRING          ;Put it into output buffer
  1148.         MOV    AL,1            ;Wait for a second
  1149.         CALL    DELAY
  1150.         POP    AX            ;Get setup string to use
  1151.         CMP    AL,0            ;Test for string 1
  1152.         JNZ    RM_30            ;No, then use string 2
  1153.         MOV    SI,OFFSET MODEM_SETUP1    ;Point to modem setup string 1
  1154.         JMP    RM_40
  1155. RM_30:
  1156.         MOV    SI,OFFSET MODEM_SETUP2    ;Point to modem setup string 2
  1157. RM_40:
  1158.         CALL    LOAD_ZSTRING        ;Load setup string to modem
  1159.         MOV    AL,1            ;Wait a second
  1160.         CALL    DELAY
  1161.         MOV    SI,OFFSET MODEM_SETUP3    ;Point to modem setup string 3
  1162.         CALL    LOAD_ZSTRING        ;Load setup string to modem
  1163.         CMP    BYTE PTR SPEED_FLAG,2    ;If speed is 1200 or 2400
  1164.         JL    RM_50            ; skip setup string 4
  1165.         MOV    AL,1            ;Wait a second
  1166.         CALL    DELAY
  1167.         MOV    SI,OFFSET MODEM_SETUP4    ;Point to modem setup string 4
  1168.         CALL    LOAD_ZSTRING        ;Load setup string to modem
  1169. RM_50:
  1170.         MOV    AL,1            ;Wait a second
  1171.         CALL    DELAY
  1172.         MOV    SI,OFFSET MODEM_SETUP5    ;Point to custom setup string 5
  1173.         CALL    LOAD_ZSTRING        ;Load setup string to modem
  1174.         CALL    CLEAR_INBUFF        ;Clear the input buffer
  1175.         POP    DX            ;Restore registers
  1176.         POP    SI
  1177. RM_EXIT:
  1178.         RET
  1179. RESET_MODEM    ENDP
  1180.  
  1181. ;----------------------------------------------------------------------
  1182. ;  Check carrier reads the carrier status signal and sets Z flag to 
  1183. ;  indicate status
  1184. ;  Input - Nothing
  1185. ;  Output - Zero flag 0 - Carrier
  1186. ;        Zero flag 1 - No Carrier detected
  1187. ;  Changes - Nothing
  1188. ;----------------------------------------------------------------------
  1189. CHECK_CARRIER    PROC    NEAR
  1190.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1191.         PUSH    AX            ;Save registers
  1192.         CMP    BYTE PTR NULL_MODEM,0    ;If null modem don't reset
  1193.         JZ    CC_10
  1194.         CMP    BYTE PTR CONNECT_FLAG,0    ;
  1195.         JZ    CC_EXIT            ;not connected, send no carrier
  1196.         MOV    AH,1            ;reset zero flag
  1197.         CMP    AH,0
  1198.         JMP    CC_EXIT            ;and return to caller
  1199. CC_10:
  1200.         PUSH    DX
  1201.         MOV    DX,COMM_PORT        ;Get the comm base address
  1202.         ADD    DX,6            ;Modem status register
  1203.         IN    AL,DX            ;Get the current status
  1204.         TEST    AL,10000000B        ;Data carrier detect
  1205.         POP    DX            ;Restore registers
  1206. CC_EXIT:
  1207.         POP    AX
  1208.         RET
  1209. CHECK_CARRIER    ENDP
  1210.  
  1211. ;----------------------------------------------------------------------
  1212. ;  DELAY - delay approximate number of seconds in AL
  1213. ;  Input - AL
  1214. ;  Output - Nothing (just waits till AL is zero)
  1215. ;  Changes - Nothing
  1216. ;----------------------------------------------------------------------
  1217. DELAY        PROC    NEAR
  1218.         PUSH    CX            ;Save registers
  1219.         PUSH    DX
  1220.         PUSH    DI
  1221.         PUSH    AX
  1222.         XOR    AH,AH            ;Read system time
  1223.         INT    1AH
  1224.         STI                ;Enable interrupts Ver 1.1
  1225.         MOV    DI,DX            ;Save low tick count
  1226.         MOV    SI,CX            ;Save high tick count
  1227.         POP    AX            ;Get number of seconds to delay
  1228.         PUSH    AX
  1229.         XOR    CX,CX            ;Zero CX
  1230.         MOV    CL,AL            ;Put seconds into loop counter
  1231. D_10:
  1232.         ADD    DI,19D            ;Approximate counts in a second
  1233.         ADC    SI,0            ;Add carry to SI
  1234.         LOOP    D_10
  1235. D_20:
  1236.         XOR    AH,AH            ;Read system time
  1237.         INT    1AH
  1238.         STI                ;Enable interrupts Ver 1.1
  1239.         CMP    SI,CX
  1240.         JNE    D_20
  1241.         CMP    DI,DX            ;End of delay time
  1242.         JGE    D_20            ;No, keep checking
  1243.         POP    AX            ;Restore registers
  1244.         POP    DI
  1245.         POP    DX
  1246.         POP    CX
  1247.         RET
  1248. DELAY        ENDP
  1249.  
  1250. ;----------------------------------------------------------------------
  1251. ;  String at SI is placed in output buffer to be sent out serial port
  1252. ;  Input - SI points to zero terminated string
  1253. ;  Output - Nothing
  1254. ;  Changes - SI
  1255. ;----------------------------------------------------------------------
  1256. LOAD_ZSTRING    PROC    NEAR
  1257.         PUSH    AX            ;Save register
  1258.         MOV    AH,1            ;Use output buffer
  1259.         CLD                ;Forward
  1260. LZ_10:
  1261.         LODSB                ;Get a byte of data
  1262.         CMP    AL,0            ;Check for zero
  1263.         JZ    LZ_EXIT         ;Yes, then exit
  1264.         CALL    PUT_BUFF_DATA        ;No, put in output buffer
  1265.         JMP    LZ_10            ;Process next data
  1266. LZ_EXIT:
  1267.         POP    AX            ;Restore register
  1268.         RET
  1269. LOAD_ZSTRING    ENDP
  1270.  
  1271. ;----------------------------------------------------------------------
  1272. ;  Check for a key in the keyboard buffer, if one is there, get it
  1273. ;  Input - Nothing
  1274. ;  Output - Zero flag = 1 no key in buffer
  1275. ;        Zero flag = 0 key is in AX
  1276. ;  Changes - AX
  1277. ;----------------------------------------------------------------------
  1278. GET_KEYSTROKE    PROC    NEAR
  1279.     ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  1280.         MOV    AH,1            ;Check for keystroke
  1281.         INT    16H            ;Keyboard BIOS
  1282.         JZ    GK_EXIT         ;No key so exit
  1283.         PUSHF                ;Save the zero flag
  1284.         XOR    AH,AH            ;Get the keystroke
  1285.         INT    16H
  1286.         POPF                ;Restore the zero flag
  1287. GK_EXIT:
  1288.         RET
  1289. GET_KEYSTROKE    ENDP
  1290.  
  1291. ;----------------------------------------------------------------------
  1292. ;  Initialize the buffer pointers for the input and output buffers.
  1293. ;  Input - CX points to starting buffer location
  1294. ;  Output - Input and output buffer points are initialized
  1295. ;  Changes - BX, CX
  1296. ;----------------------------------------------------------------------
  1297. INIT_BUFFERS    PROC    NEAR
  1298.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1299.         MOV    BX,OFFSET IN_BUFF_HEAD    ;In buffer will be here
  1300.         MOV    WORD PTR [BX],CX    ; Set head pointer to buffer
  1301.         MOV    WORD PTR 2[BX],CX    ;Set tail pointer to buffer
  1302.         MOV    WORD PTR 4[BX],CX    ;Set begin of buffer
  1303.         ADD    CX,IN_BUFF_SIZE     ;CX Points to end of in buffer
  1304. IB_10:
  1305.         MOV    WORD PTR 6[BX],CX    ;Set end of buffer
  1306.         MOV    BX,OFFSET OUT_BUFF_HEAD ;Out buffer after in buffer
  1307.         MOV    WORD PTR [BX],CX    ; Set head pointer to buffer
  1308.         MOV    WORD PTR 2[BX],CX    ;Set tail pointer to buffer
  1309.         MOV    WORD PTR 4[BX],CX    ;Set begin of buffer
  1310.         ADD    CX,OUT_BUFF_SIZE    ;CX Points to end of out buffer
  1311.         MOV    WORD PTR 6[BX],CX    ;Set end of buffer
  1312.         RET
  1313. INIT_BUFFERS    ENDP
  1314.  
  1315. ;----------------------------------------------------------------------
  1316. ;  Change the interrupt 8 vector to the interrupt service routine of
  1317. ;  PCREMOTE
  1318. ;  Input - Nothing
  1319. ;  Output - Interrupt vector 8 points to INT8
  1320. ;  Changes - AX, DX, BX, ES
  1321. ;----------------------------------------------------------------------
  1322. MODIFY_INT8    PROC    NEAR
  1323.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1324. ;
  1325. ;    Change interrupt 8 vector
  1326. ;
  1327.         MOV    AX,3508H        ;Get interrupt 8h vector
  1328.         INT    21H
  1329.         MOV    OLDINT_8,BX        ;And save it
  1330.         MOV    OLDINT_8[2],ES
  1331.         MOV    AX,2508H        ;Set interrupt 8h vector
  1332.         MOV    DX,OFFSET INT8        ; to point to new routine
  1333.         INT    21H
  1334.         RET
  1335. MODIFY_INT8    ENDP
  1336.  
  1337. ;----------------------------------------------------------------------
  1338. ;  Change the interrupt 21 vector to the interrupt service routine of
  1339. ;  PCREMOTE
  1340. ;  Input - Nothing
  1341. ;  Output - Interrupt vector 21 points to INT21
  1342. ;  Changes - AX, DX, BX, ES
  1343. ;----------------------------------------------------------------------
  1344. MODIFY_INT21    PROC    NEAR
  1345.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1346.         MOV    AX,3521H        ;Get interrupt 21H vector
  1347.         INT    21H
  1348.         MOV    WORD PTR OLDINT_21,BX    ;And save it
  1349.         MOV    WORD PTR OLDINT_21[2],ES
  1350.         MOV    AX,2521H        ;Set interrupt 21H vector
  1351.         MOV    DX,OFFSET INT21        ; to point to new routine
  1352.         INT    21H
  1353.         RET
  1354. MODIFY_INT21    ENDP
  1355.  
  1356. ;----------------------------------------------------------------------
  1357. ;  Change the communication interrupt vector to the interrupt service
  1358. ;     routine of PCREMOTE
  1359. ;  Input - SET_VEC contains interrupt vector number
  1360. ;  Output - communications interrupt vector points to INT_COMM
  1361. ;  Changes - AX, DX, BX, ES
  1362. ;----------------------------------------------------------------------
  1363. MODIFY_INTCOMM    PROC    NEAR
  1364.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1365.         PUSH    ES
  1366.         MOV    AL,BYTE PTR SET_VEC    ;Get the interrupt number
  1367.         MOV    AH,35H            ;Get the old vector
  1368.         INT    21H
  1369.         MOV    WORD PTR OLDINT_COMM,BX    ;And save it
  1370.         MOV    WORD PTR OLDINT_COMM[2],ES
  1371.         POP    ES
  1372.         MOV    AL,BYTE PTR SET_VEC    ;Get the interrupt number
  1373.         MOV    AH,25H            ;Set interrupt for comm vector
  1374.         MOV    DX,OFFSET INT_COMM    ; to point to new routine
  1375.         INT    21H
  1376.         RET
  1377. MODIFY_INTCOMM    ENDP
  1378.  
  1379. ;----------------------------------------------------------------------
  1380. ;  Set baud rate
  1381. ;  Input - AL -0 1200 baud, 1 2400 baud, 2 4800 baud, 3 9600 baud
  1382. ;        4 19200 baud, 5 38400 baud
  1383. ;  Output - Nothing
  1384. ;  Changes - Nothing
  1385. ;----------------------------------------------------------------------
  1386. SET_BAUD_RATE    PROC    NEAR
  1387.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1388.         PUSH    DX            ;Save registers
  1389.         PUSH    BX
  1390.         PUSH    SI
  1391.         PUSH    AX
  1392.         MOV    DX,COMM_PORT        ;Get port address
  1393.         ADD    DX,3            ;Line control register
  1394.         MOV    AL,83H            ;Toggle port address to
  1395.         OUT    DX,AL            ; prepare to set baud rate
  1396.         SUB    DX,2            ;Baud rate divisor MSB port
  1397.         POP    AX            ;Restore baud rate
  1398.         PUSH    AX
  1399.         XOR    AH,AH            ;Zero AH
  1400.         MOV    SI,AX            ;Save in index register
  1401.         SHL    SI,1            ;Multiply by 2, word address
  1402.         MOV    BX,OFFSET BAUD_RATE    ;Point to baud rates
  1403.         MOV    AL,[BX+SI]        ;Get baud rate MSB
  1404.         OUT    DX,AL            ; and set it
  1405.         DEC    DX            ;Baud rate divisor LSB port
  1406.         MOV    AL,1[BX+SI]        ;Get baud rate LSB
  1407.         OUT    DX,AL            ; and set it
  1408.         ADD    DX,3            ;Line control register
  1409.         MOV    AL,3            ;8 data bits,1 stop,no parity
  1410.         OUT    DX,AL            ;Set data bit pattern
  1411.                         ; and toggle port address
  1412.         POP    AX            ;Restore registers
  1413.         POP    SI
  1414.         POP    BX
  1415.         POP    DX
  1416.         RET
  1417. SET_BAUD_RATE    ENDP
  1418.  
  1419. ;----------------------------------------------------------------------
  1420. ;  Initialize the serial port
  1421. ;  Input - COMM_PORT contains port address, 
  1422. ;          COMM_FLAG 0-comm1 1-comm2 2-comm3 3-comm4
  1423. ;  Output - Serial port initialize for interrupt driven I/O
  1424. ;  Changes - Nothing
  1425. ;----------------------------------------------------------------------
  1426. INIT_SERIAL    PROC    NEAR
  1427.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1428.         PUSH    DX            ;Save registers
  1429.         PUSH    CX
  1430.         PUSH    BX
  1431.         PUSH    AX
  1432. ;
  1433. ;    disable the interrupts on the 8250 and initialize DTR and RTS
  1434. ;
  1435.         CLI                ;Disable interrupts
  1436.         MOV    DX,COMM_PORT        ;Get UART base address
  1437.         ADD    DX,4            ;Modem control register
  1438.         MOV    AL,00001011B        ;Set DTR, RTS, and OUT2
  1439.         OUT    DX,AL
  1440. ;
  1441. ;    set the baud rate of the UART and initialize line control register
  1442. ;
  1443.         CMP    BYTE PTR CONNECT_FLAG,0    ;If connect then use current
  1444.         JZ    IS_10
  1445.         MOV    AL,BYTE PTR CURRENT_SPEED
  1446.         JMP    IS_20
  1447. IS_10:
  1448.         MOV    AL,SPEED_FLAG        ;Get speed flag
  1449. IS_20:
  1450.         MOV    BYTE PTR CURRENT_SPEED,AL ;Save the current speed
  1451.         MOV    BYTE PTR SPEED_COUNT,19
  1452.         CALL    SET_BAUD_RATE
  1453. ;
  1454. ;    set 8259 mask to enable the comm port interrupt
  1455. ;
  1456.         MOV    CL,BYTE PTR SET_VEC    ;Get the interrupt number
  1457.         SUB    CL,8            ; and adjust
  1458.         MOV    AH,1            ;Mask for the interrupt
  1459.         SHL    AH,CL
  1460.         NOT    AH            ;Invert
  1461.         IN    AL,21H            ;Get current 8259 int mask
  1462.         AND    AL,AH            ;Mask appropriate int bit
  1463.         OUT    21H,AL            ;And set new 8259 mask
  1464. ;
  1465. ;    enable the data received interrupt and reset the 8250
  1466. ;
  1467.         SUB    DX,3            ;Point to int enable reg
  1468.         MOV    AL,3            ;Enable data received 
  1469.         OUT    DX,AL            ; and transmit empty int
  1470.         DEC    DX            ;Point to base address
  1471.         MOV    CX,7            ;Reset the serial port
  1472. IS_30:
  1473.         IN    AL,DX            ;Read registers to reset
  1474.         INC    DX
  1475.         LOOP    IS_30
  1476.  
  1477.         CMP    BYTE PTR COMM_INT_STA,0    ;Transmit int. running?
  1478.         JZ    IS_50            ; no, so exit
  1479.         MOV    AX,OUT_BUFF_HEAD    ;Is data in output buffer
  1480.         CMP    AX,OUT_BUFF_TAIL
  1481.         JZ    IS_50            ;No, so exit
  1482.         MOV    DX,COMM_PORT        ;Get port base address
  1483.         ADD    DX,5            ;Line status register
  1484. IS_40:
  1485.         IN    AL,DX            ;Make sure holding reg. empty
  1486.         TEST    AL,00100000B        ;Test the hold reg empty flag
  1487.         JZ    IS_40            ;Loop if not empty
  1488.         SUB    DX,5            ;Port base register
  1489.         MOV    AH,1            ;Use the output buffer
  1490.         CALL    GET_BUFF_DATA        ;Get data from output buffer
  1491.         OUT    DX,AL            ;Send the data out the port
  1492. IS_50:
  1493.         STI                ;Enable interrupts
  1494.         POP    AX            ;Restore registers
  1495.         POP    BX
  1496.         POP    CX
  1497.         POP    DX
  1498.         RET
  1499. INIT_SERIAL    ENDP
  1500.  
  1501. ;======================================================================
  1502. ;  Initialize routines.  The initialize routine for unattended is first
  1503. ;  because it must remain resident.
  1504. ;======================================================================
  1505.  
  1506. ;-----------------------------------------------------------------------------
  1507. ;  Initialize the unattended program.
  1508. ;-----------------------------------------------------------------------------
  1509. INIT_UNATTENDED PROC    NEAR
  1510.     ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  1511.         CALL    IU_10            ;Init pointers,clear video copy
  1512.         CALL    MODIFY_INT8        ;Change INT 8 vector
  1513.         CALL    MODIFY_INT21        ;Change INT 21 vector
  1514. ;
  1515. ;    Terminate-Stay-Resident
  1516. ;
  1517.         MOV    DX,VIDEO_COPY        ;Start of video copy
  1518.         ADD    DX,4000D        ;Allow room for video copy
  1519.         INT    27H            ;Terminate-Stay-Resident
  1520. ;
  1521. ;    Initialize buffer pointers and video copy pointer
  1522. ;
  1523. IU_10:
  1524.         PUSH    ES            ;Save extra segment
  1525.         MOV    CX,OFFSET INITIALIZE    ;CX points to begin of buffer
  1526.         ADD    CX,256D         ;Leave room for TSR stack
  1527.         CALL    INIT_BUFFERS        ;Initalize the buffer pointers
  1528.         INC    CX            ;Point to copy of video ram
  1529.         MOV    TEMP_VIDEO_PTR,CX    ;Save address of temp video buf
  1530.         ADD    CX,BLOCK_SIZEX2     ;Save room for temp video data
  1531.         MOV    VIDEO_COPY,CX        ;Save address of video copy
  1532. ;
  1533. ;    fill video RAM image with with space code since screen
  1534. ;    of manned system is blanked when connected
  1535. ;
  1536.         PUSH    CS            ;Video copy is destination
  1537.         POP    ES            ;ES:DI points to video copy
  1538.         MOV    DI,WORD PTR VIDEO_COPY
  1539.         MOV    AX,0720H        ;Data to fill buffer
  1540.         CLD                ;Move upward
  1541.         MOV    CX,2000D        ;Move 2000 words
  1542.         REP    STOSW            ;Fill to force screen dump
  1543.         MOV    CURSOR_POSITION,0FFFFH    ;Force cursor position update
  1544.         MOV    AL,1            ;Use setup string 2
  1545.         MOV    BYTE PTR BAD_PASSWORD,0D    ;Do not send exit code
  1546.         CALL    RESET_MODEM        ;Reset the modem
  1547.         POP    ES            ;Restore extra segment
  1548.         RET
  1549. INIT_UNATTENDED ENDP
  1550.  
  1551. ;-----------------------------------------------------------------------------
  1552. ;  INITIALIZE - Initialize the program.  Determine whether it is manned
  1553. ;  or unattended by processing the command line.  Initialize the serial
  1554. ;  port.  This area is overwritten by PCREMOTE host mode to conserve memory.
  1555. ;-----------------------------------------------------------------------------
  1556. INITIALIZE    PROC    NEAR
  1557.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1558. ;
  1559. ;    Display copyright notice.
  1560. ;
  1561.         MOV    DX,OFFSET COPYRIGHT    ;Display copyright notice
  1562.         MOV    AH,9            ;Display string
  1563.         INT    21H
  1564. ;
  1565. ;    check to see if the program is already in memory
  1566. ;
  1567.         MOV    BYTE PTR START,0    ;Zero word to avoid false match
  1568.         XOR    BX,BX            ;Initialize search segment
  1569.         MOV    AX,CS            ;Save current segment in AX
  1570.         CLD                ;Clear direction flag
  1571. I_10:
  1572.         INC    BX            ;Increment search segment
  1573.         CMP    AX,BX            ;Reached current segment?
  1574.         JE    I_20            ;Yes, PCREMOTE not resident
  1575.         MOV    ES,BX            ;Point ES to search segment
  1576.         MOV    SI,OFFSET START     ;Start of compare area
  1577.         MOV    DI,SI            ;Make offsets equal
  1578.         MOV    CX,16D            ;Check 16 characters
  1579.         REPE    CMPSB            ;Compare the strings
  1580.         JNE    I_10            ;Compare failed
  1581.         MOV    INSTALLED_SEG,BX    ;Save the segment of resident
  1582.  
  1583. ;        MOV    AH,09H            ;Print string
  1584. ;        MOV    DX,OFFSET PROG_RES    ;Display program resident mess.
  1585. ;        INT    21H
  1586. ;        INT    20H            ;Terminate
  1587.  
  1588. ;
  1589. ;    Process command line for switches.
  1590. ;
  1591. I_20:
  1592.         PUSH    CS            ;Restore ES
  1593.         POP    ES
  1594.         MOV    BX,80H            ;Point to command line length
  1595.         MOV    AH,[BX]         ;Get command line length
  1596. I_30:
  1597.         OR    AH,AH            ;Check for commands
  1598.         JNZ    I_40
  1599.         JMP    I_210            ;None, so don't look
  1600. I_40:
  1601.         INC    BX            ;Point to next data
  1602.         MOV    AL,[BX]         ;Get data
  1603.         DEC    AH            ;Decrement counter
  1604. I_50:
  1605.         CMP    AL,"?"            ;Check for help menu (usage)
  1606.         JNE    I_60            ;No, check for slash 
  1607.         JMP    HELP            ;Yes, help is requested !
  1608. I_60:        
  1609.         CMP    AL,"/"            ;Check for slash
  1610.         JNE    I_30            ;No, jump to check next data
  1611.         OR    AH,AH            ;Check for data after slash
  1612.         JNZ    I_70
  1613.         JMP    I_210            ;No, so don't process
  1614. I_70:
  1615.         INC    BX            ;Point to next data
  1616.         MOV    AL,[BX]         ;Get data
  1617.         DEC    AH            ;Decrement counter
  1618.         CMP    AL,"?"            ;Check for help after a slash
  1619.         JNE    I_80            ;No, check for comm2
  1620.         JMP    HELP            ;Yes, help is requested !
  1621. I_80:
  1622.         CMP    AL,"1"            ;Check for comm1
  1623.         JNE    I_90            ;No, check for another switch
  1624.         MOV    BYTE PTR COMM_FLAG,0    ;Set comm1 flag
  1625. I_90:
  1626.         CMP    AL,"2"            ;Check for comm2
  1627.         JNE    I_100            ;No, check for another switch
  1628.         MOV    BYTE PTR COMM_FLAG,1    ;Set comm2 flag
  1629. I_100:
  1630.         CMP    AL,"3"            ;Check for comm port 3
  1631.         JNE    I_110            ;No, jump to check next data
  1632.         MOV    BYTE PTR COMM_FLAG,2    ;Set comm3 flag
  1633. I_110:
  1634.         CMP    AL,"4"            ;Check for comm port 4
  1635.         JNE    I_120            ;No, jump to check next data
  1636.         MOV    BYTE PTR COMM_FLAG,3    ;Set comm4 flag
  1637.         JMP    I_30            ;Process next switch
  1638. I_120:
  1639.         OR    AL,20H            ;Force data to lower case
  1640.         CMP    AL,"m"            ;Check for manned switch
  1641.         JNE    I_130            ;No, check for another switch
  1642.         INC    BYTE PTR MANNED_FLAG    ;Set manned flag
  1643.         JMP    I_30            ;Process next switch
  1644. I_130:
  1645.         CMP    AL,"b"            ;Check for baud rate
  1646.         JNE    I_170            ;No, check for another switch
  1647.         OR    AH,AH            ;Check for data after slash
  1648.         JZ    I_210            ;No, so don't process
  1649.         INC    BX            ;Point to next data
  1650.         MOV    AL,[BX]         ;Get data
  1651.         DEC    AH            ;Decrement counter
  1652.         CMP    AL,"1"            ;Check for 1200 baud
  1653.         JNE    I_140
  1654.         MOV    BYTE PTR SPEED_FLAG,0    ;1200 baud
  1655.         MOV    AL,[BX+1]        ;Check for 19200 baud
  1656.         CMP    AL,"9"
  1657.         JNE    I_140            ;No so continue
  1658.         INC    BX            ;Skip this data now
  1659.         DEC    AH            ;Decrement counter
  1660.         MOV    BYTE PTR SPEED_FLAG,4    ;19200 baud
  1661.         JMP    I_30
  1662. I_140:
  1663.         CMP    AL,"2"            ;Check for 2400
  1664.         JNE    I_150
  1665.         MOV    BYTE PTR SPEED_FLAG,1    ;2400 baud
  1666. I_150:
  1667.         CMP    AL,"4"            ;Check for 4800
  1668.         JNE    I_160
  1669.         MOV    BYTE PTR SPEED_FLAG,2    ;4800 baud
  1670. I_160:
  1671.         CMP    AL,"9"            ;Check for 9600
  1672.         JNE    I_165            ;Check next speed
  1673.         MOV    BYTE PTR SPEED_FLAG,3    ;9600
  1674.         JMP    I_30            ;Process next switch
  1675. I_165:
  1676.         CMP    AL,"3"            ;Check for 38400
  1677.         JE    I_166
  1678.         JMP    I_50            ;maybe char is next slash
  1679. I_166:
  1680.         MOV    BYTE PTR SPEED_FLAG,5    ;38400
  1681.         JMP    I_30            ;Process next switch
  1682. I_170:
  1683.         CMP    AL,"d"            ;Check for desnow
  1684.         JNE    I_180            ;No, process next switch
  1685.         INC    BYTE PTR DESNOW_FLAG    ;Set desnow flag
  1686.         JMP    I_30            ;Process next switch
  1687. I_180:
  1688.         CMP    AL,"n"            ;Check for null modem
  1689.         JNE    I_190            ;No, process next switch
  1690.         INC    BYTE PTR NULL_MODEM    ;Set null modem flag
  1691.         JMP    I_30            ;Process next switch
  1692. I_190:
  1693.         CMP    AL,"s"            ;Check for smile face flag
  1694.         JNE    I_200            ;No, process next switch
  1695.         INC    BYTE PTR SMILE_FLAG    ;Yes, set smile flag
  1696.         JMP    I_30            ;No, check for more switches
  1697. I_200:
  1698.         CMP    AL,"u"            ;Check for uninstall flag
  1699.         JNE    I_205            ;No, process next switch
  1700.         JMP    UNINSTALL        ;If pcremote resident
  1701. I_205:
  1702.         JMP    I_30            ;Process next switch
  1703.  
  1704. I_210:
  1705. ;
  1706. ;  If PCREMOTE is resident and this is host mode then terminate
  1707. ;
  1708.         CMP    INSTALLED_SEG,0        ;Check for resident segment
  1709.         JZ    I_215            ;none, then ok to continue
  1710.         CMP    MANNED_FLAG,1        ;Check for manned mode
  1711.         JZ    I_215            ;yes, then continue
  1712.         MOV    AH,09H            ;Print string
  1713.         MOV    DX,OFFSET PROG_RES    ;Display program resident mess.
  1714.         INT    21H
  1715.         INT    20H            ;Terminate
  1716. ;----------------------------------------------------------------------
  1717. ;  Initialize the serial port
  1718. ;----------------------------------------------------------------------
  1719. I_215:
  1720. ;
  1721. ;    get the comm port base address using 2* comm port flag as offset
  1722. ;
  1723.         PUSH    DS            ;Save data segment
  1724.         XOR    BX,BX            ;Zero BX
  1725.         MOV    BL,COMM_FLAG        ;Get comm port flag
  1726.         MOV    SI,BX            ;Save in index register
  1727.         SHL    SI,1            ;Multiply by 2, word address
  1728.         MOV    AX,40H            ;Point DS to BIOS data area
  1729.         MOV    DS,AX
  1730.         XOR    BX,BX            ;Point to comm port address
  1731.         MOV    AX,[BX+SI]        ;Get comm port address
  1732.         POP    DS            ;Restore data segment
  1733.         CMP    AX,0            ;Make sure there is a entry
  1734.         JNZ    I_230
  1735.         CMP    BYTE PTR COMM_FLAG,2    ;Is this comm 3?
  1736.         JNZ    I_220            ;No, must be comm4
  1737.         MOV    AX,WORD PTR COMM_PORT3    ;Yes, get the comm port 3 add
  1738.         JMP    I_230
  1739. I_220:
  1740.         MOV    AX,WORD PTR COMM_PORT4
  1741. I_230:
  1742.         MOV    WORD PTR COMM_PORT,AX    ;Save comm port address
  1743. ;
  1744. ;    modify the interrupt vector for the comm port
  1745. ;
  1746.         CMP    BYTE PTR COMM_FLAG,0    ;Determine INT vector to change
  1747.         JNZ    I_240
  1748.         MOV    AL,4            ;Comm 1 interrupt 4
  1749. I_240:
  1750.         CMP    BYTE PTR COMM_FLAG,1
  1751.         JNZ    I_250
  1752.         MOV    AL,3            ;Comm 2 interrupt 3
  1753. I_250:
  1754.         CMP    BYTE PTR COMM_FLAG,2
  1755.         JNZ    I_260
  1756.         MOV    AL,BYTE PTR COMM3_INT    ;Comm 3 interrupt
  1757. I_260:
  1758.         CMP    BYTE PTR COMM_FLAG,3
  1759.         JNZ    I_270
  1760.         MOV    AL,BYTE PTR COMM4_INT    ;Comm 4 interrupt
  1761. I_270:
  1762.         ADD    AL,8            ;Interrupt number        
  1763.         CLI
  1764.         MOV    BYTE PTR SET_VEC,AL    ;
  1765.         CALL    MODIFY_INTCOMM        ;Change comm interrupt vector
  1766.         CALL    INIT_SERIAL        ;Initialize the serial port
  1767. ;
  1768. ;    determine color or monochrome and save appropriate video segment
  1769. ;
  1770.         MOV    AH,0FH            ;Determine video mode
  1771.         INT    10H            ;By using BIOS int 10
  1772.         CMP    AL,7            ;Check for monochrome
  1773.         JZ    MONOCHROME              ;Jump if it is
  1774.         MOV    WORD PTR VIDEO_SEGMENT,0B800H ;Nope, it's CGA or EGA
  1775.         JMP    I_280                  ;Skip over
  1776. MONOCHROME:
  1777.         MOV    WORD PTR VIDEO_SEGMENT,0B000H ;It's a monochrome
  1778. I_280:
  1779. ;
  1780. ;    If manned then execute manned initialization, otherwise execute
  1781. ;    unattended initialization.
  1782. ;
  1783.         CMP    BYTE PTR MANNED_FLAG,0    ;Manned or unattended
  1784.         JZ    I_290
  1785.         JMP    INIT_MANNED        ;Init the manned routines
  1786. I_290:
  1787.         JMP    INIT_UNATTENDED     ;Init the unattended routines
  1788. INITIALIZE    ENDP
  1789.  
  1790. ;----------------------------------------------------------------------
  1791. ;  Uninstall the resident (host) portion of PCREMOTE.  Make sure another
  1792. ;  program did not change any of the interrupt vectors, if so, then the
  1793. ;  vectors cannot be restored properly and the program cannot be uninstalled.
  1794. ;  Tom - if this looks like some of your code, it is, I borrowed from
  1795. ;  PRN2FILE.
  1796. ;----------------------------------------------------------------------
  1797. UNINSTALL    PROC    NEAR
  1798.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1799.         MOV    AL,08H            ;Check the timer interrupt
  1800.         CALL    CHECK_SEG
  1801.         JNE    CANT_UNINSTALL        ;If changed, can't uninstall
  1802.         MOV    AL,21H            ;Check DOS interrupt vector
  1803.         CALL    CHECK_SEG
  1804.         JNE    CANT_UNINSTALL        ;If changed, can't uninstall
  1805.         MOV    ES,INSTALLED_SEG    ;Get the segment of resident
  1806.         MOV    AL,BYTE PTR ES:SET_VEC    ;Check comm interrupt vector
  1807.         CALL    CHECK_SEG
  1808.         JNE    CANT_UNINSTALL        ;If changed, can't uninstall
  1809.         MOV    ES,INSTALLED_SEG
  1810.         ASSUME    DS:NOTHING, ES:NOTHING
  1811.         LDS    DX,DWORD PTR ES:OLDINT_8;Get original timer vector
  1812.         MOV    AX,2508H        ;and change it back
  1813.         INT    21H
  1814.         LDS    DX,DWORD PTR ES:OLDINT_21;Get original DOS vector
  1815.         MOV    AX,2521H        ;and change it back
  1816.         INT    21H
  1817. ; comm vector changed last so PCREMOTE doesn't go to sleep
  1818.         CALL    RESET_COMM        ;Reset the comm port 8250
  1819.         LDS    DX,DWORD PTR ES:OLDINT_COMM ;Get original comm vector
  1820.         MOV    AX,ES:SET_VEC        ;and change it back
  1821.         INT    21H
  1822. ; release the memory allocated to the resident portion of PCREMOTE
  1823.         MOV    ES,WORD PTR ES:2CH    ;Get the environment segment
  1824.         MOV    AH,49H            ;Free allocated memory
  1825.         INT    21H
  1826.         JC    RELEASE_ERR
  1827.         MOV    ES,INSTALLED_SEG    ;Resident program segment
  1828.         NOT    WORD PTR ES:START    ;Modify so can't find again
  1829.         MOV    AH,49H            ;Free allocated memory
  1830.         INT    21H
  1831.         JC    RELEASE_ERR        ;Error releasing the memory
  1832.         MOV    DX,OFFSET YES_UNINSTALL    ;Display uninstalled mess
  1833.         JMP    UNI_10
  1834. CANT_UNINSTALL:
  1835.         MOV    DX,OFFSET NO_UNINSTALL    ;Display can't uninstall mess
  1836.         JMP    UNI_10
  1837. RELEASE_ERR:
  1838.         MOV    DX,OFFSET CANT_RELEASE    ;Display can't release mess
  1839.         JMP    UNI_10
  1840. UNI_10:
  1841.         PUSH    CS            ;Restore the data segment
  1842.         POP    DS
  1843.         MOV    AH,09H            ;Print string
  1844.         INT    21H
  1845.         MOV    AX,4C00H
  1846.         INT    21H            ;Terminate
  1847. UNINSTALL    ENDP
  1848.  
  1849. ;----------------------------------------------------------------------
  1850. ;  Check to see if an interrupt vector points to the installed program
  1851. ;  segment.
  1852. ;  Input:  AL contains interrupt to check.
  1853. ;  Output: Zero flag = 1 if yes, else Zero flag = 0
  1854. ;  Destroys: AH, ES
  1855. ;----------------------------------------------------------------------
  1856. CHECK_SEG    PROC    NEAR
  1857.         MOV    AH,35H            ;Get vector
  1858.         INT    21H
  1859.         MOV    AX,ES            ;Save returned segment
  1860.         CMP    AX,INSTALLED_SEG    ;Is it installed segment
  1861.         RET
  1862. CHECK_SEG    ENDP
  1863.  
  1864. ;----------------------------------------------------------------------
  1865. ;  Initialize the manned program.  Initialize buffers, and change INT 8
  1866. ;  vector.
  1867. ;----------------------------------------------------------------------
  1868. INIT_MANNED    PROC    NEAR
  1869.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1870.         CALL    GET_COMSPEC
  1871.         MOV    CX,OFFSET LAST_BYTE    ;CX points to begin of buffer
  1872.         CALL    INIT_BUFFERS        ;Initalize the buffer pointers
  1873.         MOV    AX,VIDEO_SEGMENT    ;Set ES to point to video RAM
  1874.         MOV    ES,AX
  1875.         JMP    CONNECT_MANNED        ;Run manned portion of program
  1876. INIT_MANNED    ENDP
  1877.  
  1878. ;======================================================================
  1879. ;  Data used by manned portion of program only.  Not required to be
  1880. ;  resident for unattended mode.
  1881. ;======================================================================
  1882. HOST_PORT    EQU    BYTE PTR CONNECT_UNATTENDED ;Host port number (1-4) DB
  1883. OLD_CURSOR    EQU    WORD PTR HOST_PORT+1    ;Cursor position save field DW
  1884. UP_LENGTH    EQU    WORD PTR OLD_CURSOR+2    ;Upload string length DW
  1885. DN_LENGTH    EQU    WORD PTR UP_LENGTH+2    ;Download string length DW
  1886. PATH_LENGTH    EQU    WORD PTR DN_LENGTH+2    ;Pathname string length DW
  1887. LAST_KEY    EQU    BYTE PTR PATH_LENGTH+2    ;Last key pressed save field DB
  1888. EXEC_VAL    EQU    BYTE PTR LAST_KEY+1    ;Shell Variable (1-3) DB
  1889.                         ; 1 = Remote shell to DOS
  1890.                         ; 2 = Remote Download
  1891.                         ; 3 = Remote Upload
  1892. UPDN_STRING    EQU    BYTE PTR EXEC_VAL+1     ;Upload string (filename)
  1893. PATH_STRING    EQU    BYTE PTR UPDN_STRING+44    ;Path string (drive & path)
  1894. ORGDSK        EQU    BYTE PTR PATH_STRING+44    ;1 byte
  1895. ORGPTH        EQU    BYTE PTR ORGDSK+1    ;256 bytes
  1896. BLOCK_DATA_COUNT DB    0            ;Number of bytes left to rec.
  1897. TYPE_TRANSFER    DB    0FFH            ;FF - No data transfer in prog.
  1898.                         ;00 - Received char. data
  1899.                         ;01 - Received attr. data
  1900. RPT_STATUS    DB    0            ;00 - No data repeat
  1901.                         ;02 - Repeat the char in block
  1902. CUR_STATUS    DB    0            ;0=No cursor data being rec.
  1903.                         ; otherwise, byte count
  1904. CUR_LOW     DB    0            ;Low byte of cursor data
  1905. CUR_HIGH    DB    0            ;High byte of cursor data
  1906. ENTER_NUMBER    DB    CR,LF,CR,LF,"Enter phone number:$"
  1907. NO_CARRIER    DB    CR,LF,"No carrier.$"
  1908. MODEM_ERROR    DB    CR,LF,"Error.$"
  1909. TERMINATE_MESS    DB    CR,LF,"Returning to DOS.$"
  1910. PROG_RES    DB    CR,LF,"PCREMOT2 is already resident.$"
  1911. NO_UNINSTALL    DB    CR,LF,"Cannot uninstall PCREMOT2.$"
  1912. YES_UNINSTALL    DB    CR,LF,"PCREMOT2 uninstalled successfully.$"
  1913. CANT_RELEASE    DB    CR,LF,"Error release PCREMOT2 resident memory.$"
  1914. SHELL_PROMPT    DB    " Shell to DOS initiated.  Type 'EXIT' at any DOS "
  1915.         DB    "prompt to return to PCREMOT2. ",0
  1916. TRANSFER_PROMPT    DB    " File transfer initiated ... ",0
  1917. PARM_$_1200    DB    "/a /8 /r",0        ;ZCOPY parm 1200 baud
  1918. PARM_$_2400    DB    "/a /7 /r",0        ;ZCOPY parm 2400 baud
  1919. PARM_$_4800    DB    "/a /6 /r",0        ;ZCOPY parm 4800 baud
  1920. PARM_$_9600    DB    "/a /5 /r",0        ;ZCOPY parm 9600 baud
  1921. PARM_$_19200    DB    "/a /4 /r",0        ;ZCOPY parm 19200 baud
  1922. PARM_$_38400    DB    "/a /3 /r",0        ;ZCOPY parm 38400 baud
  1923. PARM_STRING    DB    "         ",0    ;Actual ZCOPY parm
  1924. ASCII_CODE    DB    "~`!1@2#3$4%5^6&7*8(9)0_-+|\=QWERTYUIOP{[}]ASDFGHJKL:;"
  1925.         DB    34D,39D,CR,"ZXCVBNM<,>.?/ "
  1926. 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
  1927.         DB    13,13,14,14,17,18,19,20,21,22,23,24,25,26,27,27,28,28
  1928.         DB    31,32,33,34,35,36,37,38,39,40,40,41,41,43,46,47,48,49
  1929.         DB    50,51,52,53,53,54,54,55,55,61
  1930. ZCOPY        DB    "ZCOPY ",0        ;ZCOPY command line
  1931. REMOTE_COM    DB    "COM ",0         ;Remote Comm value
  1932. HOST_COM    DB    "COM ",0        ;Host Comm value
  1933. UPDNLOAD_COM    DB    " /c zcopy  ", 90 DUP(?)
  1934. HELP_SCREEN    DB    CR,LF
  1935.         DB    " Usage  :  PCREMOT2 [ /# ] [ /B# ] [ /M ] [ /D ] [ /S ] [ /N ]"
  1936.         DB    CR,LF,CR,LF
  1937.         DB    " [ /#  ]   - # = Communication port number ( 1 - 4 ) "
  1938.         DB    CR,LF
  1939.         DB    " [ /B# ]   - # = Baud rate 1=1200, 2=2400, 4=4800, 9=9600 "
  1940.         DB    CR,LF
  1941.         DB    "                 null modem only  19=19200, 3=38400 "
  1942.         DB    CR,LF
  1943.         DB    " [ /M  ]   - Manned mode (used on remote computer) "
  1944.         DB    CR,LF
  1945.         DB    " [ /D  ]   - Desnow flag (used on CGA monitors) "
  1946.         DB    CR,LF
  1947.         DB    " [ /S  ]   - Smile face enable (used on host computer) "
  1948.         DB    CR,LF
  1949.         DB    " [ /N  ]   - Null modem connects the two computers "
  1950.         DB    CR,LF
  1951.         DB    " [ /U  ]   - Uninstall (used on host computer to remove from memory) "
  1952.         DB    CR,LF,CR,LF,"$",26
  1953. EXIT_MESSAGE    DB    "                        "
  1954.         DB    "  ┌──────────────────┐  "
  1955.         DB    "  │ OK to EXIT? (Y/N)│  "
  1956.         DB    "  └──────────────────┘  "
  1957.         DB    "                        "
  1958. BOX_CHAR    DW    164    ;location for character
  1959.         DB    '╔'    ;Character for box
  1960.         DW    256
  1961.         DB    '╗'
  1962.         DW    324
  1963.         DB    '║'
  1964.         DW    416
  1965.         DB    '║'
  1966.         DW    484
  1967.         DB    '╠'
  1968.         DW    576
  1969.         DB    '╣'
  1970.         DW    644
  1971.         DB    '║'
  1972.         DW    804
  1973.         DB    '║'
  1974.         DW    964
  1975.         DB    '║'
  1976.         DW    1124
  1977.         DB    '║'
  1978.         DW    736
  1979.         DB    '║'
  1980.         DW    896
  1981.         DB    '║'
  1982.         DW    1056
  1983.         DB    '║'
  1984.         DW    1216
  1985.         DB    '║'
  1986.         DW    1284
  1987.         DB    '╠'
  1988.         DW    1376
  1989.         DB    '╣'
  1990.         DW    1444
  1991.         DB    '║'
  1992.         DW    1536
  1993.         DB    '║'
  1994.         DW    1604
  1995.         DB    '╚'
  1996.         DW    1696
  1997.         DB    '╝'
  1998. TRANSFER_MESS    DB    "FILE TRANSFER REQUESTED",0
  1999.         DB    " ",0
  2000.         DB    " (U)pload - Send file(s) to Host System.",0
  2001.         DB    "                   or",0
  2002.         DB    " (D)ownload - Receive file(s) from Host.",0
  2003. UPLOAD_MESS    DB    "   UPLOAD REQUESTED",0
  2004.         DB    "Enter the full pathname of the file(s) on ",0
  2005.         DB    "the remote system which you want to upload",0
  2006.         DB    "to the host system.",0
  2007.         DB    ":",0
  2008. DOWNLOAD_MESS    DB    "  DOWNLOAD REQUESTED",0
  2009.         DB    "Enter the full pathname of the file(s) on ",0
  2010.         DB    "the host system which you want to download",0
  2011.         DB    "to the remote system.",0
  2012.         DB    ":",0
  2013. UP_PATH_MESS    DB    "   UPLOAD REQUESTED",0
  2014.         DB    "Enter the path on the host system to place ",0
  2015.         DB    "the uploaded file(s).  No target, other",0
  2016.         DB    "than directory path, may be specified.",0
  2017.         DB    ":",0
  2018. DN_PATH_MESS    DB    "  DOWNLOAD REQUESTED",0
  2019.         DB    "Enter the path on the remote system to place",0
  2020.         DB    "the downloaded file(s).  No target, other",0
  2021.         DB    "than directory path, may be specified.",0
  2022.         DB    ":",0
  2023. PRESS_ESC    DB    "Press <ESC> to return to PCREMOT2",0
  2024. ;
  2025. ;-----------------------------------------------------------------------
  2026. ;                  
  2027. COMSPC        LABEL    DWORD
  2028. COM_OFS     DW    0000
  2029. COM_SEG     DW    0000
  2030.  
  2031. PAR_BLK     DW    0000
  2032.         DW    0000            ; OFFSET NUL_TAIL
  2033.         DW    0000
  2034.         DW    0000
  2035.         DD    0FFFFH
  2036. NOEXEC        DB    00
  2037. ;--------------------------------------------------------------------
  2038. ;
  2039. COM_VAR     DB    'COMSPEC='
  2040. NUL_TAIL    DB    00
  2041. ;
  2042. ; DON'T REMOVE OR PHYSICALLY REARRANGE THIS
  2043. ;
  2044. GODPMT        DB    '$P$G',00
  2045. PMTSTR        DB    'PROMPT=',00
  2046. PMTLOC        DW    0000
  2047. DFTPMT        DB    'PROMPT='
  2048. PCRSTR        DB    'DOS SHELL- '
  2049. PMTLGT        DW    $-OFFSET PCRSTR
  2050.  
  2051. ;======================================================================
  2052. ;  The manned routine will execute the connect manned routine to call the
  2053. ;  unattended system.  These routines are only used in the manned mode.
  2054. ;======================================================================
  2055.  
  2056. ;----------------------------------------------------------------------
  2057. ; User requested a help screen by including a question mark in the 
  2058. ; command line.  Therefore, display the usage for PCREMOTE and end
  2059. ; the program.
  2060. ;----------------------------------------------------------------------
  2061. HELP        PROC    NEAR
  2062.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2063.         PUSH    CS            ;
  2064.         POP    DS            ;DS->CS
  2065.         MOV    AH,09H            ;String print INT21 (09)
  2066.         MOV    DX,OFFSET HELP_SCREEN    ;DS:DX->Help screen variable
  2067.         INT    21H            ;Display the help screen
  2068.         INT    20H            ;Terminate the program
  2069. HELP        ENDP
  2070.  
  2071. ;----------------------------------------------------------------------
  2072. ;  Connect manned asks for the phone number to call, dials the number
  2073. ;  and waits for connect.  Once connected it sends bursts of 20 CRs at
  2074. ;  one second intervals.  When it receives alpha data it processes video
  2075. ;  data and waits for sync byte (00), then transfers control to the
  2076. ;  manned routine.
  2077. ;----------------------------------------------------------------------
  2078. CONNECT_MANNED    PROC    NEAR
  2079.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2080.         PUSH    ES            ;
  2081.         PUSH    CS            ;
  2082.         POP    ES            ;
  2083.         MOV    BX,1000H        ;
  2084.         MOV    AH,4AH            ;
  2085.         INT    21H            ;
  2086.         POP    ES            ;
  2087. CM_10:
  2088.         CMP    BYTE PTR NULL_MODEM,0    ;If null modem skip number
  2089.         JNZ    CM_50
  2090.         XOR    AL,AL            ;Use setup string 1
  2091.         CALL    RESET_MODEM        ;Reset the modem first
  2092.         MOV    DX,OFFSET ENTER_NUMBER    ;Point to enter number mess.
  2093.         MOV    AH,9            ;Display message
  2094.         INT    21H
  2095.         MOV    DX,OFFSET UPDN_STRING    ;Unused area as keyboard buffer
  2096.         MOV    BX,DX            ;Enter max characters for input
  2097.         MOV    BYTE PTR [BX],40D
  2098.         MOV    AH,0AH            ;Buffered keyboard input
  2099.         INT    21H            ;Get the phone number
  2100.         MOV    AL,1            ;Wait a second
  2101.         CALL    DELAY
  2102.         MOV    SI,OFFSET UPDN_STRING    ;Point to phone number
  2103.         INC    SI            ;Amount of data in key buffer
  2104.         XOR    AX,AX            ;Zero AX
  2105.         CLD                ;Forward
  2106.         LODSB                ;Get count
  2107.         OR    AL,AL            ;Check for no input
  2108.         JNZ    CM_20            ;If there is then continue
  2109.         JMP    EXIT_MANNED        ;No, then exit program
  2110. CM_20:
  2111.         PUSH    SI            ;Save pointer
  2112.         MOV    SI,OFFSET TONE_DIAL    ;Send the tone dial command
  2113.         CALL    LOAD_ZSTRING
  2114.         POP    SI            ;Restore pointer
  2115.         ADD    SI,AX            ;Point to end of buffer
  2116.         INC    SI            ;Include CR code
  2117.         MOV    BYTE PTR [SI],0     ;And put a zero on end
  2118.         DEC    SI            ;Adjust for previous INC
  2119.         SUB    SI,AX            ;Back to begin of buffer
  2120.         CALL    LOAD_ZSTRING        ;Dial the phone number
  2121.         MOV    AL,1            ;Wait a second
  2122.         CALL    DELAY
  2123.         CALL    CLEAR_INBUFF        ;Clear input buffer
  2124. CM_30:
  2125.         CALL    GET_KEYSTROKE        ;Check for a keystroke
  2126.         JZ    CM_40            ;None, so wait
  2127.         CMP    AL,ESC_KEY        ;Check for ESCAPE
  2128.         JNZ    CM_40            ;No
  2129.         JMP    CM_10            ;Yes, then enter new number
  2130. CM_40:
  2131.         CALL    CHECK_CARRIER        ;Check for a connect signal
  2132.         JZ    CM_60            ;No, then check for err codes
  2133. CM_50:
  2134.         CALL    CLEAR_SCREEN        ;Yes, blank the screen
  2135.         MOV    BYTE PTR CONNECT_FLAG,1 ;Set the connect flag
  2136.         JMP    CM_90            ;Execute manned
  2137. CM_60:
  2138.         MOV    AH,0            ;Use input buffer
  2139.         CALL    GET_BUFF_DATA        ;Get data from buffer
  2140.         JNC    CM_30            ;No data, try again
  2141.         CMP    AL,"3"            ;No carrier code?
  2142.         JNZ    CM_80            ;No, check for other code
  2143. CM_70:        
  2144.         MOV    DX,OFFSET NO_CARRIER    ;Send no carrier message
  2145.         MOV    AH,09H
  2146.         INT    21H
  2147.         JMP    CM_10            ;Yes, reset modem and try again
  2148. CM_80:
  2149.         CMP    AL,"8"            ;2400 no answer code
  2150.         JZ    CM_70            ;Yes, display no carrier mess
  2151.         CMP    AL,"4"            ;Error code?
  2152.         JNZ    CM_30            ;No, check for other code
  2153.         MOV    DX,OFFSET MODEM_ERROR    ;Send modem command error mess
  2154.         MOV    AH,09H
  2155.         INT    21H
  2156.         JMP    CM_10            ;Yes, reset modem and try again
  2157. CM_90:
  2158.         MOV    AL,1            ;Wait for a second
  2159.         CALL    DELAY
  2160.         MOV    BYTE PTR CR_COUNT,30D    ;Send 30 CRs at a time
  2161. CM_100:
  2162.         CALL    CHECK_CARRIER        ;Check for carrier loss
  2163.         JNZ    CM_110            ;No, then continue
  2164.         JMP    EXIT_MANNED        ;Yes, then exit
  2165. CM_110:
  2166.         CALL    GET_KEYSTROKE        ;Check for a keystroke
  2167.         JZ    CM_120            ;None, so wait
  2168.         CMP    AL,ESC_KEY        ;Check for ESCAPE
  2169.         JNZ    CM_120            ;No
  2170.         JMP    EXIT_MANNED        ;Yes, give up
  2171. CM_120:
  2172.         MOV    AX,OUT_BUFF_TAIL    ;Is output buffer empty?
  2173.         CMP    AX,OUT_BUFF_HEAD
  2174.         JNZ    CM_130            ;No, skip CR
  2175.         MOV    AL,CR            ;Send a CR for speed sync
  2176.         MOV    AH,1            ;Use output buffer
  2177.         CALL    PUT_BUFF_DATA
  2178.         DEC    BYTE PTR CR_COUNT    ;Decrement CR counter
  2179.         JZ    CM_90
  2180. CM_130:
  2181.         MOV    AH,0            ;Use input buffer
  2182.         CALL    GET_BUFF_DATA        ; and check for data
  2183.         JNC    CM_100            ;No data so keep checking
  2184.         CMP    AL,'@'            ;Alpha message?
  2185.         JL    CM_100            ;No, then wait for it
  2186. CM_140:
  2187.         CMP    BYTE PTR NULL_MODEM,0    ;Using a null modem ?
  2188.         JZ    CM_150            ;No... no need for exit check
  2189.         PUSH    AX            ;Store AX just in case
  2190.         MOV    AH,AL            ;Set up AX for exit compare
  2191.         XOR    AL,AL            ;Reset AL to zero
  2192.         CMP    WORD PTR EXIT_CODE,AX    ;Did host send exit_code ?
  2193.         POP    AX            ;Restore AX just in case no
  2194.         JNZ    CM_150            ;No check for sync byte
  2195.         JMP    EXIT_MANNED        ;Yes, exit back to DOS
  2196. CM_150:
  2197.         CMP    AL,0            ;Is data a sync byte
  2198.         JNE    CM_270            ;No, then put data on screen
  2199. CM_160:                     ;
  2200.         MOV    AH,0            ;Input buffer
  2201.         CALL    GET_BUFF_DATA        ;Receive a character
  2202.         JNC    CM_160            ;Did we receive one yet ?
  2203.         CMP    AL,0            ;Sync byte ?
  2204.         JE    CM_160            ;Yes
  2205. ;
  2206. ; A character was received that is not a sync byte.  This is the host trying
  2207. ; to tell the remote computer what Comm port the host is currently running
  2208. ; through. Because garbage (line noise) is always a threat, remote must
  2209. ; accurately determine which Comm port was sent.
  2210. ;
  2211.         PUSH    CX            ;Store register
  2212.         PUSH    DX            ;Store register
  2213.         XOR    CX,CX            ;Reset counters to zero
  2214.         XOR    DX,DX            ;Reset counters to zero
  2215.         JMP    CM_180            ;Process AL data
  2216. CM_170:                    
  2217.         MOV    AH,0            ;Use input buffer
  2218.         CALL    GET_BUFF_DATA        ;Receive a character
  2219.         JNC    CM_170            ;Did we get one yet ?
  2220.         CMP    AL,0            ;Sync byte ?
  2221.         JE    CM_220            ;Yes, determine host comm
  2222. CM_180:
  2223.         CMP    AL,1D            ;One received ?
  2224.         JNE    CM_190            ;No
  2225.         INC    CL            ;Yes, bump Comm 1 counter
  2226. CM_190:
  2227.         CMP    AL,2D            ;Two received ?
  2228.         JNE    CM_200            ;No
  2229.         INC    CH            ;Yes, bump Comm 2 counter
  2230. CM_200:
  2231.         CMP    AL,3D            ;Three received ?
  2232.         JNE    CM_210            ;No
  2233.         INC    DL            ;Yes, bump Comm 3 counter
  2234. CM_210:
  2235.         CMP    AL,4D            ;Four received ?
  2236.         JNE    CM_170            ;No, get another character
  2237.         INC    DH            ;Yes, bump Comm 4 counter
  2238.         JMP    CM_170            ;Get another character
  2239. CM_220:
  2240.         MOV    AL,'1'            ;Assume Comm 1 for now
  2241.         CMP    CH,CL            ;Comm2 count > Comm1 count ?
  2242.         JLE    CM_230            ;No
  2243.         MOV    AL,'2'            ;Yes, assume Comm2 for now
  2244.         MOV    CL,CH            ;Save Comm2 counter in CL
  2245. CM_230:
  2246.         CMP    DL,CL            ;Comm3 count > CL (current)
  2247.         JLE    CM_240            ;No
  2248.         MOV    AL,'3'            ;Yes, assume Comm3 for now
  2249.         MOV    CL,DL            ;Save Comm3 counter in CL
  2250. CM_240:
  2251.         CMP    DH,CL            ;Comm4 count > CL (current)
  2252.         JLE    CM_250            ;No
  2253.         MOV    AL,'4'            ;Yes, Host port = Comm4 
  2254. CM_250:                    
  2255.         MOV    HOST_PORT,AL        ;Save largest port counter
  2256.         POP    DX            ;Restore register
  2257.         POP    CX            ;Restore register
  2258.         CALL    MAKE_PARM_STRING    ;Make ZCOPY parm w/ baud & comm
  2259. CM_260:
  2260.         CALL    GET_BUFF_DATA        ;Receive a character
  2261.         JNC    CM_260            ;Did we receive one yet ?
  2262.         CMP    AL,0            ;Sync Byte ?
  2263.         JNE    CM_270            ;Yes
  2264.         CALL    CLEAR_SCREEN        ;Blank the screen
  2265.         JMP    MANNED            ;We're in, let's run program
  2266. CM_270:
  2267.         MOV    DL,AL            ;Prepare to display character
  2268.         MOV    AH,2            ; using DOS
  2269.         INT    21H            ;Display it
  2270. CM_280:
  2271.         CALL    CHECK_CARRIER        ;Check for carrier loss
  2272.         JNZ    CM_290            ;No, then continue
  2273.         JMP    EXIT_MANNED        ;Yes, then exit
  2274. CM_290:
  2275.         CALL    GET_KEYSTROKE        ;Check for a keystroke
  2276.         JZ    CM_310            ;If none, skip next routine
  2277. ;
  2278. ;    Check for exit code, if it is then exit
  2279. ;
  2280.         CMP    AX,WORD PTR EXIT_CODE    ;Check for exit code
  2281.         JNZ    CM_300            ;No, so continue
  2282.         CALL    CONFIRM_EXIT        ;Yes, confirm exit
  2283.         JNZ    CM_310            ;No, so continue, don't send
  2284.         JMP    EXIT_MANNED        ;Otherwise reset and exit
  2285. CM_300:
  2286.         CALL    SEND_KEYSTROKE        ;Send to unattended system
  2287. CM_310:
  2288.         MOV    AH,0            ;Use input buffer
  2289.         CALL    GET_BUFF_DATA        ; and check for data
  2290.         JNC    CM_280            ;No data, check for keys
  2291.         JMP    CM_140            ;Check for sync byte
  2292. CONNECT_MANNED    ENDP
  2293.  
  2294. ;----------------------------------------------------------------------
  2295. ; MAKE_PARM_STRING creates the ZCOPY parameters using the current baud
  2296. ; rate of the remote system. This PROC also creates REMOTE_COM using
  2297. ; the COMM_FLAG.  REMOTE_COM is used in MAKE_UP_COM & MAKE_DN_COM. 
  2298. ;----------------------------------------------------------------------
  2299. MAKE_PARM_STRING    PROC    NEAR
  2300.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2301.         PUSH    AX            ;Store registers & flags
  2302.         PUSH    CX
  2303.         PUSH    DS
  2304.         PUSH    ES
  2305.         PUSH    DI
  2306.         PUSH    SI
  2307.         PUSHF
  2308.         CLD                ;Direction flag -> forward
  2309.         PUSH    CS
  2310.         PUSH    CS
  2311.         POP    DS            ;DS->CS
  2312.         POP    ES            ;ES->CS
  2313.         MOV    DI,OFFSET PARM_STRING    ;DI->Parm string's first char
  2314.         MOV    SI,OFFSET PARM_$_1200    ;SI->1st char of 1200 var.
  2315.         CMP    BYTE PTR SPEED_FLAG,1D    ;2400 Baud ?
  2316.         JNE    MPS_10            ;Yes, use 2400 baud variable
  2317.         MOV    SI,OFFSET PARM_$_2400    ;SI->1st char of 2400 var.
  2318. MPS_10:
  2319.         CMP    BYTE PTR SPEED_FLAG,2D    ;4800 Baud ?
  2320.         JNE    MPS_20            ;Yes, use 4800 baud variable
  2321.         MOV    SI,OFFSET PARM_$_4800    ;SI->1st char of 4800 var.
  2322. MPS_20:
  2323.         CMP    BYTE PTR SPEED_FLAG,3D    ;9600 Baud ?
  2324.         JNE    MPS_30
  2325.         MOV    SI,OFFSET PARM_$_9600    ;SI->1st char of 9600 var.
  2326. MPS_30:
  2327.         CMP    BYTE PTR SPEED_FLAG,4D    ;19200 Baud ?
  2328.         JNE    MPS_32
  2329.         MOV    SI,OFFSET PARM_$_19200    ;SI->1st char of 19200 var.
  2330. MPS_32:
  2331.         CMP    BYTE PTR SPEED_FLAG,5D    ;38400 Baud ?
  2332.         JNE    MPS_34
  2333.         MOV    SI,OFFSET PARM_$_38400    ;SI->1st char of 38400 var.
  2334. MPS_34:
  2335.         MOV    CX,8D            ;Move 8 letters
  2336. MPS_40:
  2337.         LODSB                ;Pick off char. and place it
  2338.         STOSB                ; in the real ZCOPY parm string
  2339.         LOOP    MPS_40            ;11 characters done ?
  2340. ;
  2341. ; Remote comm must be set up using COMM_FLAG
  2342. ;
  2343.         MOV    DI,OFFSET REMOTE_COM    ;ES:DI-> (C)om var. 1st char
  2344.         ADD    DI,3D            ;ES:DI-> COM( ) var. 4th char
  2345.         MOV    AL,'1'            ;Assume remote using com1
  2346.         CMP    BYTE PTR COMM_FLAG,1D    ;Using com2 ?
  2347.         JNE    MPS_50            ;No
  2348.         MOV    AL,'2'            ;Remote using com2
  2349. MPS_50:
  2350.         CMP    BYTE PTR COMM_FLAG,2D    ;Using com3 ?
  2351.         JNE    MPS_60            ;No
  2352.         MOV    AL,'3'            ;Remote using com3
  2353. MPS_60:
  2354.         CMP    BYTE PTR COMM_FLAG,3D    ;using com4?
  2355.         JNE    MPS_70            ;No
  2356.         MOV    AL,'4'            ;Remote using com4
  2357. MPS_70:
  2358.         STOSB                ;Store com (1-4) variable
  2359. ;
  2360. ; HOST_COM must be set up using the HOST_PORT variable.
  2361. ;
  2362.         MOV    AL,HOST_PORT        ;Ready AL for STOSB
  2363.         MOV    DI,OFFSET HOST_COM    ;ES:DI->1st char of HOST_COM
  2364.         ADD    DI,3D            ;ES:DI->4th char of HOST_COM
  2365.         STOSB                ;Store HOST_COM into variable
  2366.         POPF                ;Restore flags & registers
  2367.         POP    SI
  2368.         POP    DI
  2369.         POP    ES
  2370.         POP    DS
  2371.         POP    CX
  2372.         POP    AX
  2373.         RET
  2374. MAKE_PARM_STRING    ENDP
  2375.  
  2376. ;----------------------------------------------------------------------
  2377. ;  Manned portion of the program.  Not RAM resident.  Sends keystrokes
  2378. ;  to the unattended computer.    Data from unattended computer is
  2379. ;  decoded and processed.
  2380. ;----------------------------------------------------------------------
  2381. MANNED        PROC    NEAR
  2382.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2383. ;
  2384. ;    Check for loss of carrier
  2385. ;
  2386.         CALL    CHECK_CARRIER        ;No, check for carrier loss
  2387.         JNZ    M_10            ;No loss so continue
  2388.         JMP    EXIT_MANNED        ;Otherwise reset and exit
  2389. ;
  2390. ;    Check to see if shift status has changed, if so, put new status
  2391. ;    in the output buffer
  2392. ;
  2393. M_10:
  2394.         MOV    AH,2              ; Prepare shift status
  2395.         INT    16H              ; Get shift status
  2396.         CMP    SHIFT_STATUS,AL       ; See if the same
  2397.         JE    M_20              ; If so, next routine
  2398.         MOV    SHIFT_STATUS,AL       ; Save new status
  2399.         MOV    AL,0FDH           ; Sync, expect shift
  2400.         MOV    AH,1              ; Put into out buff
  2401.         CALL    PUT_BUFF_DATA          ;
  2402.         MOV    AL,SHIFT_STATUS       ; Get shift status
  2403.         CALL    PUT_BUFF_DATA          ; Send to host system
  2404. ;
  2405. ;    Check for keystoke, if so, put the ASCII code and scan code
  2406. ;    into the output buffer, check it for exit code
  2407. ;
  2408. M_20:
  2409.         CALL    GET_KEYSTROKE        ;Check for keystroke
  2410.         JNZ    M_30
  2411.         JMP    M_90            ;If none skip this routine
  2412. ;
  2413. ; Check for shell to DOS, if it is then shell & return
  2414. ;
  2415. M_30:
  2416.         CMP    AX,WORD PTR SHELL_CODE    ; Shell key pressed ?
  2417.         JNE    M_40            ; No....
  2418.         MOV    EXEC_VAL,1D        ; Tell EXEC to shell
  2419.         CALL    EXEC_ZCOPY        ; EXEC to shell
  2420.         CALL    INIT_SERIAL        ; Re-initialize serial port
  2421.         CALL    CLEAR_SCREEN        ; Clear the remote screen    
  2422.         MOV    AX,WORD PTR CLEAR_CODE    ; Send clear_code to
  2423.         CALL    SEND_KEYSTROKE        ;  rewrite entire screen
  2424.         JMP    M_90            ; Process next char
  2425. ;
  2426. ; Check for exit code, if it is then exit
  2427. ;
  2428. M_40:        
  2429.         CMP    AX,WORD PTR EXIT_CODE    ;Check for exit code
  2430.         JNZ    M_50            ;No, so continue
  2431.         PUSH    DX            ; Store DX
  2432.         CALL    GET_CURSOR        ; Get cursor pos.
  2433.         MOV    OLD_CURSOR,DX        ; Save Cursor pos.
  2434.         MOV    DH,25D            ; Place cursor
  2435.         MOV    DL,79D            ;            off screen
  2436.         CALL    PUT_CURSOR        ; Set cursor pos.
  2437.         POP    DX            ; Restore DX
  2438.         CALL    CONFIRM_EXIT        ;Yes, confirm exit
  2439.         PUSH    DX            ; Store DX
  2440.         MOV    DX,OLD_CURSOR        ; Restore cursor pos.
  2441.         CALL    PUT_CURSOR        ; Set cursor pos.
  2442.         POP    DX            ; Restore DX
  2443.         JNZ    M_90            ;No, so continue, don't send
  2444.         JMP    EXIT_MANNED        ;Otherwise reset and exit
  2445. ;
  2446. ; Check for transfer code, if it is then ask to upload or download
  2447. ;
  2448. M_50:                          ;
  2449.         CMP    AX,WORD PTR TRANSFER_CODE ; Check for transfer
  2450.         JNZ    M_70              ; No, so continue
  2451.         PUSH    DX              ; Store register
  2452.         CALL    GET_CURSOR          ; Get cursor position
  2453.         MOV    OLD_CURSOR,DX          ; Save cursor in old cursor
  2454.         MOV    DH,25D              ; Cursor Row = 25
  2455.         MOV    DL,79D              ; Cursor Col = 79
  2456.         CALL    PUT_CURSOR          ; Position Cursor
  2457.         POP    DX              ; Restore DX register
  2458.         CALL    TRANSFER_TYPE          ; Transfer file
  2459.         CMP    AX,WORD PTR CLEAR_CODE      ; Transferred files ?
  2460.         JNE    M_60              ; Yes-reset remote scrn
  2461.         CALL    INIT_SERIAL          ; Re-initialize serial port
  2462.         CALL    CLEAR_INBUFF
  2463.         CALL    CLEAR_OUTBUFF
  2464.         JMP    M_70              ; Send clear screen code
  2465. M_60:
  2466.         PUSH    DX              ; Push DX register
  2467.         MOV    DX,OLD_CURSOR          ; Put cursor back
  2468.         CALL    PUT_CURSOR          ; where it was
  2469.         POP    DX              ; Restore DX register
  2470.         JMP    M_90              ; Transfer complete
  2471. ;
  2472. ; Check for clear and resend entire screen code.
  2473. ;
  2474. M_70:                          ;
  2475.         CMP    AX,WORD PTR CLEAR_CODE      ; Clear screen pressed?
  2476.         JNZ    M_80              ; No...
  2477.         PUSH    AX              ; Yes.... save key
  2478.         CALL    CLEAR_SCREEN          ; Clear remote screen
  2479.         POP    AX              ; Restore key
  2480. M_80:                          ;
  2481.         CALL    SEND_KEYSTROKE          ; Send key to host
  2482. ;
  2483. ; Check for receive data, if available, get data and decode
  2484. ;
  2485. M_90:
  2486.         MOV    AH,0            ;Get data from input buffer
  2487.         CALL    GET_BUFF_DATA
  2488.         JC    M_100            ;Data is there, so process
  2489.         JMP    M_EXIT            ;No data,so loop again
  2490. M_100:
  2491.         CMP    BYTE PTR TYPE_TRANSFER,0FFH ;Check transfer type
  2492.         JZ    M_160            ;If ff, check for sync byte
  2493.         CMP    VID_RAM_OFFSET,0FFFFH    ;Received block no. yet?
  2494.         JNZ    M_120            ;Yes, then process as data
  2495.         MOV    BYTE PTR BLOCK_DATA_COUNT,BLOCK_SIZE ;Data counter
  2496.         MOV    BX,BLOCK_SIZEX2     ;Get block size in bytes
  2497.         MUL    BX            ;Block number X block size
  2498.         ADD    AL,TYPE_TRANSFER    ;Adjust for char. or attr.
  2499.         MOV    VID_RAM_OFFSET,AX    ;Save pointer to video RAM
  2500.         JMP    M_EXIT
  2501. M_120:
  2502.         MOV    DI,VID_RAM_OFFSET    ;Point to video RAM
  2503.         CMP    BYTE PTR RPT_STATUS,0    ;Check the repeat flag
  2504.         JZ    M_140            ;Normal data transfer
  2505.         MOV    CL,BYTE PTR BLOCK_DATA_COUNT ;Number to repeat
  2506.         XOR    CH,CH
  2507. M_130:
  2508.         CALL    PUT_VIDEO_DATA        ;Store the data in video RAM
  2509.         INC    DI            ;Point to next video RAM loc.
  2510.         LOOP    M_130
  2511.         JMP    M_150            ;End of data, reset variables
  2512. M_140:
  2513.         CALL    PUT_VIDEO_DATA        ;Store the data in video RAM
  2514.         INC    DI            ;Point to next video RAM loc.
  2515.         MOV    VID_RAM_OFFSET,DI      ;And save pointer
  2516.         DEC    BYTE PTR BLOCK_DATA_COUNT ;Dec. data counter
  2517.         JZ    M_150              ;End of data, reset variables
  2518.         JMP    M_EXIT            ;Otherwise continue
  2519. M_150:
  2520.         MOV    BYTE PTR TYPE_TRANSFER,0FFH ;Reset type transfer flag
  2521.         JMP    M_EXIT
  2522. M_160:
  2523.         CMP    BYTE PTR CUR_STATUS,0    ;Check cursor status
  2524.         JZ    M_170            ;If 0, check for sync byte
  2525.         XOR    BX,BX            ;Zero BX for index
  2526.         MOV    BL,BYTE PTR CUR_STATUS    ;Use as index for cursor data
  2527.         MOV    DI,OFFSET CUR_STATUS    ;Base address for cursor data
  2528.         MOV    [DI+BX],AL        ;Save the register data
  2529.         INC    BL            ;Increment count
  2530.         MOV    BYTE PTR CUR_STATUS,BL    ;And save it
  2531.         CMP    BL,3            ;Check to see if we have 3 byte
  2532.         JNZ    M_EXIT            ;No, so wait till enough data
  2533.         MOV    BH,0            ;Always use page one
  2534.         MOV    DX,WORD PTR CUR_LOW    ;Get cursor position
  2535.         MOV    AH,2            ;Set cursor function
  2536.         INT    10H
  2537.         MOV    BYTE PTR CUR_STATUS,0    ;Reset cursor status
  2538.         JMP    M_EXIT
  2539. M_170:
  2540.         PUSH    AX            ;Save the data
  2541.         AND    AL,0FCH         ;Mask out data type and repeat
  2542.         CMP    AL,0FCH         ;Video data sync?
  2543.         JNZ    M_180            ;No, check for cursor sync
  2544.         POP    AX            ;Restore data
  2545.         PUSH    AX
  2546.         AND    AL,1            ;Save data type
  2547.         MOV    TYPE_TRANSFER,AL    ;Set transfer type flag
  2548.         POP    AX            ;Restore data
  2549.         AND    AL,2            ;Save repeat flag
  2550.         MOV    RPT_STATUS,AL        ;Set repeat flag
  2551.         MOV    VID_RAM_OFFSET,0FFFFH    ;Prepare to receive block no.
  2552.         JMP    M_EXIT
  2553. M_180:
  2554.         POP    AX            ;Restore data
  2555.         CMP    AL,0D2H         ;Check for cursor data sync
  2556.         JNZ    M_EXIT            ;If not, then throw away
  2557.         MOV    BYTE PTR CUR_STATUS,1    ;Set cursor status byte
  2558. M_EXIT:
  2559.         JMP    MANNED            ;Do it again
  2560. MANNED        ENDP
  2561.  
  2562. ;----------------------------------------------------------------------
  2563. ;  Exit manned.  The exit code is sent, interrupt vector reset, and
  2564. ;  the modem is hung up and reset
  2565. ;  Input - Nothing
  2566. ;  Output - DOS
  2567. ;  Changes - everything
  2568. ;----------------------------------------------------------------------
  2569. EXIT_MANNED    PROC    NEAR
  2570.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2571.         MOV    AX,WORD PTR EXIT_CODE    ;Get the exit code
  2572.         CALL    SEND_KEYSTROKE        ;Send the exit code
  2573.         CALL    CLEAR_SCREEN         ;Blank the screen
  2574.         MOV    DX,OFFSET TERMINATE_MESS ;Display terminate call mess.
  2575.         MOV    AH,09H
  2576.         INT    21H
  2577.         XOR    AL,AL            ;Reset modem and exit
  2578.         CALL    RESET_MODEM
  2579.         MOV    AL,1            ;Wait a second
  2580.         CALL    DELAY
  2581.         CALL    RESET_COMM
  2582.         LDS    DX,DWORD PTR OLDINT_COMM ;Get original comm vector
  2583.         MOV    AX,SET_VEC        ;and change it back
  2584.         INT    21H
  2585.         INT    20H            ;Terminate program
  2586. EXIT_MANNED    ENDP
  2587.  
  2588. ;----------------------------------------------------------------------
  2589. ;  Reset comm port.  Resets the comm port 8250 and disables interrupt
  2590. ;  driven I/O.  Reset the 8259 mask.
  2591. ;----------------------------------------------------------------------
  2592. RESET_COMM    PROC    NEAR
  2593.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2594.         PUSH    ES
  2595.         PUSH    DS
  2596.         PUSH    CS
  2597.         POP    DS
  2598.         CMP    INSTALLED_SEG,0        ;Maybe this is uninstall
  2599.         JZ    EM_10
  2600.         MOV    ES,INSTALLED_SEG    ;Get location of resident prog
  2601.         MOV    DX,ES:COMM_PORT        ;Get the comm port it used
  2602.         MOV    CL,BYTE PTR ES:SET_VEC    ;Determine mask bit to change
  2603.         JMP    EM_20
  2604. EM_10:
  2605.         MOV    DX,CS:COMM_PORT        ;Get port address
  2606.         MOV    CL,BYTE PTR SET_VEC    ;Determine mask bit to change
  2607. EM_20:
  2608.         INC    DX            ;Interrupt enable reg.
  2609.         XOR    AL,AL
  2610.         OUT    DX,AL            ;Disable all interrupts
  2611.         SUB    CL,8            ; and adjust
  2612.         MOV    AH,1
  2613.         SHL    AH,CL            ;Select the mask bit to set
  2614.         IN    AL,21H            ;Get current 8259 int mask
  2615.         OR    AL,AH            ;Set appropriate int bit
  2616.         OUT    21H,AL            ;And set new 8259 mask
  2617.         POP    DS
  2618.         POP    ES            ;Restore segment
  2619.         RET
  2620. RESET_COMM    ENDP
  2621.  
  2622. ;----------------------------------------------------------------------
  2623. ;  Clear screen.  This routine will blank the video display
  2624. ;  Input - Nothing
  2625. ;  Output - Screen is cleared
  2626. ;  Changes - AX, BX, CX, DX
  2627. ;----------------------------------------------------------------------
  2628. CLEAR_SCREEN    PROC    NEAR
  2629.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2630.         MOV    BX,0            ;Use video page one
  2631.         MOV    DX,0            ;Position cursor at row 0 col 0
  2632.         MOV    AH,2            ;Set cursor function
  2633.         INT    10H
  2634.         MOV    AX,0700H        ;Scroll down, clear screen
  2635.         MOV    BH,07H            ;White on black
  2636.         MOV    CX,0            ;Upper left corner
  2637.         MOV    DH,24D            ;Lower right corner
  2638.         MOV    DL,79D
  2639.         INT    10H            ;Video BIOS call
  2640.         RET
  2641. CLEAR_SCREEN    ENDP
  2642.  
  2643. ;----------------------------------------------------------------------
  2644. ;  Display OK to exit message and wait for response
  2645. ;  Input - Nothing
  2646. ;  Output - Zero flag set - exit, zero flag reset - do not exit
  2647. ;  Changes - CX, SI, DI
  2648. ;----------------------------------------------------------------------
  2649. CONFIRM_EXIT    PROC    NEAR
  2650.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2651.         PUSH    AX            ;Save the exit code
  2652. CE_10:
  2653.         MOV    AX,OUT_BUFF_HEAD    ;Wait until the out buffer
  2654.         CMP    AX,OUT_BUFF_TAIL    ; is empty
  2655.         JNZ    CE_10
  2656. ;
  2657. ;  Save the existing video data in the output buffer
  2658. ;
  2659.         CALL    SWITCH_DS_ES
  2660.         MOV    DI,ES:OUT_BUFF_END    ;Use output buffer as temp stor.
  2661.         MOV    SI,0            ;Upper left corner of video
  2662.         MOV    CX,5            ;Transfer 5 lines
  2663. CE_20:
  2664.         PUSH    CX            ;Save line counter
  2665.         MOV    CX,24D            ;Transfer 24 char. per line
  2666.         REPNZ    MOVSW
  2667.         ADD    SI,112D         ;Next line
  2668.         POP    CX            ;Restore line counter
  2669.         LOOP    CE_20
  2670. ;
  2671. ;  Display the ok to exit message
  2672. ;
  2673.         CALL    SWITCH_DS_ES
  2674.         MOV    DI,0            ;Upper left corner of video
  2675.         MOV    SI,OFFSET EXIT_MESSAGE    ;Exit message
  2676.         MOV    CX,5            ;Display 5 lines
  2677. CE_30:
  2678.         PUSH    CX            ;Save line counter
  2679.         MOV    CX,24D            ;Display 20 characters per line
  2680. CE_40:
  2681.         LODSB
  2682.         CALL    PUT_VIDEO_DATA        ;Display the character
  2683.         MOV    AL,70H            ;White on black attribute
  2684.         CALL    PUT_VIDEO_DATA        ;Store attribute
  2685.         LOOP    CE_40
  2686.         ADD    DI,112D         ;Next line
  2687.         POP    CX            ;Restore line counter
  2688.         LOOP    CE_30
  2689. ;
  2690. ;  Wait for keystroke and convert to lower case
  2691. ;
  2692. CE_50:
  2693.         CALL    GET_KEYSTROKE        ;Check for keystroke
  2694.         JZ    CE_50            ;None there, try again
  2695.         OR    AL,20H            ;Convert to lower case
  2696. ;
  2697. ;  Restore the saved video data
  2698. ;
  2699.         MOV    SI,OUT_BUFF_END        ;Old video is in output buffer
  2700.         MOV    DI,0            ;Upper left corner of video
  2701.         MOV    CX,5            ;Transfer 5 lines
  2702. CE_60:
  2703.         PUSH    CX            ;Save line counter
  2704.         MOV    CX,24D            ;Transfer 24 char. per line
  2705.         REPNZ    MOVSW
  2706.         ADD    DI,112D         ;Next line
  2707.         POP    CX            ;Restore line counter
  2708.         LOOP    CE_60
  2709.         CMP    AL,'y'            ;Check for yes, all others no
  2710.         POP    AX            ;Restore exit code
  2711.         RET
  2712. CONFIRM_EXIT    ENDP
  2713.  
  2714. ;---------------------------------------------------------------
  2715. ; Draw the box and display the text in it.
  2716. ; Input - SI points to the text strings
  2717. ; Output - Current video stored in output buffer, text displayed 
  2718. ;          in box.
  2719. ; Changes - nothing
  2720. ;---------------------------------------------------------------
  2721. DISPLAY_BOX    PROC    NEAR
  2722.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2723.         PUSH    AX            ;Save registers
  2724.         PUSH    BX
  2725.         PUSH    CX
  2726.         PUSH    DI
  2727.         PUSH    SI
  2728. ;
  2729. ; Save the current video area in the output buffer
  2730. ;
  2731.         CALL    SWITCH_DS_ES
  2732.         MOV    DI,ES:OUT_BUFF_END    ;Use output buffer as temp stor.
  2733.         XOR    SI,SI            ;Upper left of video
  2734.         MOV    CX,12            ;Save 12 lines
  2735. DB_10:
  2736.         PUSH    CX            ;Save the line counter
  2737.         MOV    CX,51            ;Save 51 columns
  2738.         REPNZ    MOVSW
  2739.         ADD    SI,58            ;Adjust to start of next line
  2740.         POP    CX            ;Restore line counter
  2741.         LOOP    DB_10
  2742.         CALL    SWITCH_DS_ES
  2743. ;
  2744. ; Blank that area of the screen
  2745. ;
  2746.         XOR    DI,DI            ;Upper left of video
  2747.         MOV    CX,12            ;Blank 12 lines
  2748. DB_20:
  2749.         PUSH    CX            ;Save line counter
  2750.         MOV    CX,51            ;Blank 51 characters
  2751. DB_30:
  2752.         MOV    AL,SPACE        ;Space character
  2753.         CALL    PUT_VIDEO_DATA        ;Display the character
  2754.         MOV    AL,70H            ;Attribute
  2755.         CALL    PUT_VIDEO_DATA
  2756.         LOOP    DB_30
  2757.         ADD    DI,58            ;Adjust to start of next line
  2758.         POP    CX            ;Restore line counter
  2759.         LOOP    DB_20
  2760. ;
  2761. ; Draw the box
  2762. ;
  2763.         MOV    DI,166            ;First line of box
  2764.         CALL    DRAW_LINE        ;Display the horizontal line
  2765.         MOV    DI,486            ;Second line of box
  2766.         CALL    DRAW_LINE        ;Display the horizontal line
  2767.         MOV    DI,1286            ;Third line of box
  2768.         CALL    DRAW_LINE        ;Display the horizontal line
  2769.         MOV    DI,1606            ;Fourth line of box
  2770.         CALL    DRAW_LINE        ;Display the horizontal line
  2771.         MOV    BX,OFFSET BOX_CHAR    ;Get a pointer to box corners
  2772.         MOV    CX,20            ;Corners and vertical lines
  2773. DB_40:
  2774.         MOV    DI,[BX]            ;Get offset to char location
  2775.         ADD    BX,2            ;Point to character
  2776.         MOV    AL,[BX]            ;Get the character
  2777.         INC    BX            ;Next corner
  2778.         CALL    PUT_VIDEO_DATA
  2779.         LOOP    DB_40
  2780. ;
  2781. ; Draw the text in the box
  2782. ;
  2783.         POP    SI            ;Get pointer to text
  2784.         PUSH    SI
  2785.         MOV    DI,348            ;Location for title line
  2786.         CALL    DRAW_TEXT        ;Display the line of text
  2787.         MOV    DI,648            ;Next line of text
  2788.         CALL    DRAW_TEXT        ;Display the line of text
  2789.         MOV    DI,808            ;Next line of text
  2790.         CALL    DRAW_TEXT        ;Display the line of text
  2791.         MOV    DI,968            ;Next line of text
  2792.         CALL    DRAW_TEXT        ;Display the line of text
  2793.         MOV    DI,1128            ;Next line of text
  2794.         CALL    DRAW_TEXT        ;Display the line of text
  2795.         MOV    DI,1458            ;Next line of text
  2796.         MOV    SI,OFFSET PRESS_ESC    ;Display the press ESC to exit
  2797.         CALL    DRAW_TEXT        ;Display the line of text
  2798.         POP    SI            ;Restore registers
  2799.         POP    DI
  2800.         POP    CX
  2801.         POP    BX
  2802.         POP    AX
  2803.         RET
  2804. DISPLAY_BOX    ENDP
  2805.  
  2806. ;---------------------------------------------------------------
  2807. ; Draw horizontal line
  2808. ; Input ES:DI points to location to start drawing the line
  2809. ; Output - nothing
  2810. ; Changes - AL, CX, DI
  2811. ;---------------------------------------------------------------
  2812. DRAW_LINE    PROC    NEAR
  2813.         MOV    CX,45            ;45 Columns in line
  2814.         MOV    AL,'═'            ;Line draw character
  2815. DL_10:
  2816.         CALL    PUT_VIDEO_DATA        ;Display the character
  2817.         INC    DI            ;Adjust past attribute
  2818.         LOOP    DL_10
  2819.         RET
  2820. DRAW_LINE    ENDP
  2821.  
  2822. ;---------------------------------------------------------------
  2823. ; Display line of text
  2824. ; Input - SI points to text DI points to video location
  2825. ; Output - line of text is displayed on the screen
  2826. ; Changes - AL, SI, DI
  2827. ;---------------------------------------------------------------
  2828. DRAW_TEXT    PROC    NEAR
  2829.         LODSB                ;Get the text
  2830.         CMP    AL,0            ;Is this the end of the string
  2831.         JZ    DT_10            ;Yes
  2832.         CALL    PUT_VIDEO_DATA        ;Display the character
  2833.         INC    DI
  2834.         JMP    DRAW_TEXT
  2835. DT_10:
  2836.         RET
  2837. DRAW_TEXT    ENDP
  2838.  
  2839. ;---------------------------------------------------------------
  2840. ; Restore the video saved to display a box
  2841. ; Input - nothing
  2842. ; Output - nothing
  2843. ; Changes - nothing
  2844. ;---------------------------------------------------------------
  2845. RESTORE_BOX    PROC    NEAR
  2846.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  2847.         PUSH    AX            ;Save registers
  2848.         PUSH    CX
  2849.         PUSH    DI
  2850.         PUSH    SI
  2851.         MOV    SI,OUT_BUFF_END        ;Old video in output buffer
  2852.         XOR    DI,DI            ;Upper left corner of screen
  2853.         MOV    CX,12            ;Line counter
  2854. RB_10:
  2855.         PUSH    CX            ;Save line counter
  2856.         MOV    CX,51            ;51 characters per line
  2857.         REPNZ    MOVSW
  2858.         ADD    DI,58            ;Next line
  2859.         POP    CX            ;Restore line counter
  2860.         LOOP    RB_10
  2861.         POP    SI            ;Restore registers
  2862.         POP    DI
  2863.         POP    CX
  2864.         POP    AX
  2865.         RET
  2866. RESTORE_BOX    ENDP
  2867.  
  2868. ;---------------------------------------------------------------
  2869. ; Display (U)pload or (D)ownload message and wait for response    
  2870. ; Input - Nothing                              
  2871. ; Output -                                  
  2872. ; Changes - CX, SI, DI                               
  2873. ;---------------------------------------------------------------
  2874. TRANSFER_TYPE    PROC    NEAR                        
  2875.        ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING            
  2876.         MOV    AX,OUT_BUFF_HEAD    ;Wait until the out
  2877.         CMP    AX,OUT_BUFF_TAIL    ;buffer is empty
  2878.         JNZ    TRANSFER_TYPE
  2879. ;
  2880. ; Display the (U)pload or (D)ownload message
  2881. ;
  2882.         MOV    SI,OFFSET TRANSFER_MESS ;Transfer message
  2883.         CALL    DISPLAY_BOX
  2884. ;
  2885. ; Wait for a keystroke and convert to lower case
  2886. ;
  2887. TT_10:
  2888.         CALL    GET_KEYSTROKE        ;Check for a keystroke
  2889.         JZ    TT_10            ;None there, try again
  2890.         OR    AL,20H
  2891.         CALL    RESTORE_BOX
  2892.         CMP    AL,'u'            ;Upload Requested ?
  2893.         JZ    TT_20            ;Yes
  2894.         JMP    TT_90            ;No, so continue
  2895. TT_20:                        ;UPLOAD CODING HERE
  2896.         MOV    LAST_KEY,0        ;Clear last key pressed
  2897.         CALL    UPLOAD            ;Ask for upload file
  2898.         CMP    LAST_KEY,ESC_KEY    ;ESC pressed ?
  2899.         JNZ    TT_30            ;No
  2900.         JMP    TT_180            ;Yes - return to PCREMOTE
  2901. TT_30:
  2902.         MOV    LAST_KEY,0        ;Clear last key pressed
  2903.         MOV    SI,OFFSET UP_PATH_MESS    ; Path message for upload
  2904.         CALL    PATH            ;Get destination Path
  2905.         CMP    LAST_KEY,ESC_KEY    ;ESC pressed ?
  2906.         JNZ    TT_40            ;No
  2907.         JMP    TT_180            ;Yes - return to PCREMOTE
  2908. TT_40:
  2909.         MOV    LAST_KEY,0        ;Clear last key pressed
  2910.         CALL    MAKE_UP_COM        ;Create ZCOPY EXEC com
  2911.         CLD                ;Forward direction ptr.
  2912.         MOV    SI,OFFSET ZCOPY     ;DS:SI -- ZCOPY variable
  2913.         CALL    SEND_STRING        ;Send ZCOPY command line
  2914.         MOV    SI,OFFSET HOST_COM    ;DS:SI -- COM variable
  2915.         CALL    SEND_STRING        ;Send COM to host
  2916.         MOV    AL,SPACE        ;AL = SPACE
  2917.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2918.         MOV    SI,OFFSET PATH_STRING    ;DS:SI -- Path variable
  2919.         MOV    CX,PATH_LENGTH        ;CX = Length of PATH
  2920.         CMP    CX,0            ;Default Path ?
  2921.         JE    TT_60            ;Yes...
  2922. TT_50:                        ;No...
  2923.         LODSB                ;AL = next character
  2924.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2925.         LOOP    TT_50            ;All characters sent ?
  2926.         MOV    AL,SPACE        ;AL = SPACE
  2927.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2928. TT_60:
  2929.         MOV    SI,OFFSET PARM_STRING    ;DS:SI -- PARM variable
  2930.         MOV    CX,9D
  2931. TT_70:
  2932.         LODSB                ;AL = Next character
  2933.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2934.         LOOP    TT_70            ;All characters sent ?
  2935.         MOV    AL,CR            ;AL = carriage return
  2936.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2937. TT_80:
  2938.         MOV    AX,OUT_BUFF_HEAD    ;Get the buff head ptr
  2939.         CMP    AX,OUT_BUFF_TAIL    ;Test for data
  2940.         JNZ    TT_80            ;Wait until buffer empty
  2941.         MOV    EXEC_VAL,3D        ;Tell EXEC to upload
  2942.         CALL    EXEC_ZCOPY        ;Shell to DOS & EXEC ZCOPY
  2943.         JMP    TT_170            ;Transfer complete, exit
  2944. TT_90:
  2945.         CMP    AL,'d'            ;Download Requested ?
  2946.         JZ    TT_100            ;Yes
  2947.         JMP    TT_180            ;No so return to PCREMOTE
  2948. TT_100:                        ;DOWNLOAD CODING HERE
  2949.         MOV    LAST_KEY,0        ;Clear last key pressed
  2950.         CALL    DOWNLOAD        ;Ask for filename
  2951.         CMP    LAST_KEY,ESC_KEY    ;ESC pressed ?
  2952.         JNZ    TT_110            ;No
  2953.         JMP    TT_180            ;Yes, return to PC_REMOTE
  2954. TT_110:
  2955.         MOV    LAST_KEY,0        ;Clear last key pressed
  2956.         MOV    SI,OFFSET DN_PATH_MESS    ; Path message for download
  2957.         CALL    PATH            ;Get destination Path
  2958.         CMP    LAST_KEY,ESC_KEY    ;ESC pressed ?
  2959.         JNZ    TT_120            ;No
  2960.         JMP    TT_180            ;Yes, return to PC_REMOTE
  2961. TT_120:
  2962.         MOV    LAST_KEY,0        ;Clear last key pressed
  2963.         CALL    MAKE_DN_COM        ;Create ZCOPY EXEC com
  2964.         CLD                ;Forward direction flag
  2965.         MOV    SI,OFFSET ZCOPY     ;DS:SI -- ZCOPY variable
  2966.         CALL    SEND_STRING        ;Send ZCOPY command
  2967.         MOV    SI,OFFSET UPDN_STRING    ;DS:SI -- file variable
  2968.         MOV    CX,DN_LENGTH        ;CX = length of filename
  2969.         CMP    CX,0            ;Default Filename
  2970.         JE    TT_140            ;Yes...
  2971. TT_130:                        ;No...
  2972.         LODSB                ;AL = next character
  2973.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2974.         LOOP    TT_130            ;All characters sent ?
  2975.         MOV    AL,SPACE        ;AL = SPACE
  2976.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2977. TT_140:
  2978.         MOV    SI,OFFSET HOST_COM    ;DS:SI -- Com variable
  2979.         CALL    SEND_STRING        ;Send COM variable
  2980.         MOV    AL,SPACE        ;AL = SPACE
  2981.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2982.         MOV    SI,OFFSET PARM_STRING    ;DS:SI -- PARM variable
  2983.         MOV    CX,9D
  2984. TT_150:
  2985.         LODSB                ;AL = next character
  2986.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2987.         LOOP    TT_150            ;All characters sent ?
  2988.         MOV    AL,CR            ;AL = carriage return
  2989.         CALL    GET_SEND_CODE        ;Get & send scan-code
  2990. TT_160:
  2991.         MOV    AX,OUT_BUFF_HEAD    ;Get buffer head ptr
  2992.         CMP    AX,OUT_BUFF_TAIL    ;Test for data in buff
  2993.         JNZ    TT_160            ;Wait for buffer empty
  2994.         MOV    EXEC_VAL,2D        ;Tell EXEC to download
  2995.         CALL    EXEC_ZCOPY        ;Shell to DOS - EXEC ZCOPY
  2996.         JMP    TT_170
  2997. TT_170:
  2998.         MOV    AX,WORD PTR CLEAR_CODE    ;Tell the caller to clear
  2999.         JMP    TT_190            ;the remote's screen
  3000. TT_180:
  3001.         MOV    AX,WORD PTR TRANSFER_CODE ;Tell the caller that
  3002. TT_190:                        ;screen doesn't need to
  3003.         RET                ;be rewritten.
  3004. TRANSFER_TYPE    ENDP
  3005.  
  3006. ;------------------------------------------------------------
  3007. ; Display upload message then wait for filename(s).            
  3008. ; Input - Nothing                            
  3009. ; Output -                                
  3010. ; Changes - CX,SI,DI                            
  3011. ;                                     
  3012. ;------------------------------------------------------------
  3013. UPLOAD        PROC    NEAR                       
  3014.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING          
  3015.         MOV    AX,OUT_BUFF_HEAD    ;Wait until the out
  3016.         CMP    AX,OUT_BUFF_TAIL    ;buffer is empty
  3017.         JNZ    UPLOAD
  3018.         MOV    SI,OFFSET UPLOAD_MESS    ;Upload message
  3019.         CALL    DISPLAY_BOX
  3020.         PUSH    DX            ;Save register
  3021.         MOV    DH,7            ;Put cursor in row 8
  3022.         MOV    DL,5            ;Put cursor in column 6
  3023.         CALL    PUT_CURSOR        ;Set Cursor
  3024.         POP    DX            ;Restore register
  3025.         PUSH    ES            ;Store ES
  3026.         PUSH    DS            ;Store DS
  3027.         POP    ES            ;ES = DS
  3028.         MOV    DI,OFFSET UPDN_STRING    ;ES:DI -> UP_string
  3029.         MOV    CX,42D            ;MAX length = 42
  3030.         CALL    GETSTRING        ;Receive file
  3031.         MOV    LAST_KEY,AL        ;Save last key
  3032.         MOV    UP_LENGTH,CX        ;Save length
  3033.         CMP    UP_LENGTH,0        ;Any file selected ?
  3034.         JNE    UP_10            ;Yes
  3035.         MOV    LAST_KEY,ESC_KEY    ;No...Return (esc)
  3036. UP_10:
  3037.         POP    ES            ;Restore ES
  3038.         CALL    RESTORE_BOX
  3039.         RET
  3040. UPLOAD        ENDP
  3041.  
  3042. ;------------------------------------------------------------
  3043. ; Display download message then wait for response.          
  3044. ; Input - Nothing                            
  3045. ; Output -                               
  3046. ; Changes - CX,SI,DI                            
  3047. ;------------------------------------------------------------
  3048. DOWNLOAD    PROC    NEAR                       
  3049.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING          
  3050.         MOV    AX,OUT_BUFF_HEAD    ;Wait until the
  3051.         CMP    AX,OUT_BUFF_TAIL    ;out buffer is empty
  3052.         JNZ    DOWNLOAD
  3053.         MOV    SI,OFFSET DOWNLOAD_MESS ;Download message
  3054.         CALL    DISPLAY_BOX
  3055.         PUSH    DX            ;Save DX register
  3056.         MOV    DH,7            ;Put cursor in row 8
  3057.         MOV    DL,5            ;Put cursor in column 6
  3058.         CALL    PUT_CURSOR        ;Put cursor there
  3059.         POP    DX            ;Restore register
  3060.         PUSH    ES            ;Store ES
  3061.         PUSH    DS            ;Store DS
  3062.         POP    ES            ;ES = DS
  3063.         MOV    DI,OFFSET UPDN_STRING    ;ES:DI -> DN_string
  3064.         MOV    CX,42D            ;MAX length = 42
  3065.         CALL    GETSTRING        ;Get filename
  3066.         MOV    LAST_KEY,AL        ;Save last key
  3067.         MOV    DN_LENGTH,CX        ;Save length
  3068.         CMP    DN_LENGTH,0        ;File selected ?
  3069.         JNE    DN_10            ;Yes
  3070.         MOV    LAST_KEY,ESC_KEY    ;No... return (esc)
  3071. DN_10:
  3072.         POP    ES            ;Restore ES
  3073.         CALL    RESTORE_BOX
  3074.         RET
  3075. DOWNLOAD    ENDP
  3076.  
  3077. ;---------------------------------------------------------------------- 
  3078. ; Display the path request screen & prompt user to input path name.    
  3079. ; Input - SI points to display message for transfer
  3080. ; Output - Path Message Displayed on screen.
  3081. ; Changes - CX,SI,DI
  3082. ;----------------------------------------------------------------------
  3083. PATH        PROC    NEAR                           
  3084.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING               
  3085.         MOV    AX,OUT_BUFF_HEAD    ; Wait until the
  3086.         CMP    AX,OUT_BUFF_TAIL    ; out buffer is empty
  3087.         JNZ    PATH
  3088.         CALL    DISPLAY_BOX
  3089.         PUSH    DX            ; Save DX Register
  3090.         MOV    DH,7            ; Put cursor in row 8
  3091.         MOV    DL,5            ; Put cursor in col 6
  3092.         CALL    PUT_CURSOR        ; Put cursor there
  3093.         POP    DX            ; Restore DX
  3094.         PUSH    ES            ; Store ES
  3095.         PUSH    DS            ; Store DS
  3096.         POP    ES            ; ES = DS
  3097.         MOV    DI,OFFSET PATH_STRING    ; ES:DI -> Path_string
  3098.         MOV    CX,42D            ; Max length = 42
  3099.         CALL    GETSTRING        ; Get path
  3100.         MOV    LAST_KEY,AL        ; Save last key
  3101.         MOV    PATH_LENGTH,CX        ; Save length
  3102. ;
  3103. ; Validate and correct (modify) pathname if ZCOPY will not accept the
  3104. ; string entered for the pathname.
  3105. ; i.e.- C:\ is acceptable whereas C: is unacceptable 
  3106. ; C:\DOS is acceptable whereas C:\DOS\ is unacceptable.
  3107. ;
  3108.         CMP    LAST_KEY,ESC_KEY    ; ESC key pressed ?
  3109.         JE    PATH_20            ; Yes, so skip pathname edit
  3110.         MOV    SI,OFFSET PATH_STRING    ; SI->1st char of path name
  3111.         ADD    SI,PATH_LENGTH        ; SI->1 char after pathname
  3112.         DEC    SI            ; SI->Last char of pathname
  3113.         LODSB                ; Pick off last char
  3114.         CMP    AL,':'            ; Is last char a colon
  3115.         JNE    PATH_10            ; No, check other chars.
  3116.         PUSH    SI            ; Save SI into DI
  3117.         POP    DI            ; DI = SI
  3118.         MOV    AL,'\'            ; Add backslash to pathname
  3119.         STOSB                ; Store the backslash
  3120.         INC    PATH_LENGTH        ; Add one to length of path
  3121.         JMP    PATH_20            ; Editting is complete
  3122. PATH_10:
  3123.         CMP    AL,'\'            ; Is last char a backslash
  3124.         JNE    PATH_20            ; No, skip pathname edit
  3125.         DEC    SI            ; SI -> Last char again
  3126.         DEC    SI            ; SI -> 2nd last char
  3127.         LODSB                ; Pick off 2nd last char
  3128.         CMP    AL,':'            ; 2nd last char a colon ?
  3129.         JE    PATH_20            ; Yes, so skip edit.
  3130.         PUSH    SI            ; Store SI for DI
  3131.         POP    DI            ; DI-> Last char of pathname
  3132.         MOV    AL,SPACE         ; Clear last char of path
  3133.         STOSB                ; Store blank
  3134.         DEC    PATH_LENGTH        ; Subtract 1 from path length
  3135. PATH_20:
  3136.               POP    ES
  3137.         CALL    RESTORE_BOX
  3138.         RET
  3139. PATH        ENDP
  3140.  
  3141. ;----------------------------------------------------------------------
  3142. ; Create the Upload command string that the REMOTE computer EXECS    
  3143. ;---------------------------------------------------------------------- 
  3144. MAKE_UP_COM    PROC    NEAR
  3145.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  3146.         PUSH    AX            ;Store registers
  3147.         PUSH    CX
  3148.         PUSH    DS
  3149.         PUSH    ES
  3150.         PUSH    DI
  3151.         PUSH    SI
  3152.         PUSHF
  3153.         PUSH    CS
  3154.         PUSH    CS
  3155.         POP    DS            ;DS -> CS
  3156.         POP    ES            ;ES -> CS
  3157.         CLD                ;Forward Direction Flag
  3158.         MOV    DI,OFFSET UPDNLOAD_COM    ;DI -> 1st char of upload com
  3159.         ADD    DI,10D            ;DI -> 10th char of upl. com
  3160.         MOV    AL,SPACE        ;Reset com string w/ 89
  3161.         MOV    CX,89D            ; blanks 
  3162. MUC_10:
  3163.         STOSB                ;Fill sting with AL
  3164.         LOOP    MUC_10            ;89 chars complete ?
  3165.         SUB    DI,89D            ;DI -> 10th char of upl. com
  3166.         MOV    SI,OFFSET UPDN_STRING    ;SI -> 1st char of upl. file
  3167.         MOV    CX,UP_LENGTH        ;CX = length of string
  3168. MUC_20:
  3169.         LODSB                ;AL = char from filename
  3170.         STOSB                ;Upl. com gets char
  3171.         LOOP    MUC_20            ;All chars copied ?
  3172.         MOV    AL,SPACE        ;Place a blank char at the 
  3173.         STOSB                ; end of filename
  3174.         MOV    SI,OFFSET REMOTE_COM    ;SI -> 1st char of comm var.
  3175.         MOV    CX,4D            ;Pick off 4 characters
  3176. MUC_30:
  3177.         LODSB                ;Pick off 1 char 
  3178.         STOSB                ;Place in upl. com string
  3179.         LOOP    MUC_30            ;Entire string done ?
  3180.         MOV    AL,SPACE         ;Place a blank at end of comm
  3181.         STOSB                ; string in upl. com string
  3182.         MOV    SI,OFFSET PARM_STRING    ;SI -> 1st char of parm
  3183.         ADD    SI,3D            ;SI -> 4th char of parm
  3184.         MOV    CX,5D            ;Pick off 5 chars from parm
  3185. MUC_40:
  3186.         LODSB                ;Pick off 1 char
  3187.         STOSB                ;Place char in upl. com 
  3188.         LOOP    MUC_40            ;6 characters done yet ?
  3189. MUC_50:
  3190.         MOV    AL,CR            ;Carriage return
  3191.         STOSB
  3192.         MOV    AL,0            ;0 to end string
  3193.         STOSB
  3194. ;
  3195. ; Length of UPDNLOAD_COM must be inserted in the first character of the
  3196. ; string ("?/c zcopy..."), therefore the length must be determined.
  3197. ;
  3198.         MOV    SI,OFFSET UPDNLOAD_COM    ;SI-> 1st char of string
  3199.         CALL    GET_STRING_LEN        ;CX = Length of string
  3200.         MOV    AL,CL            ;Ready AL for STOSB instruct.
  3201.         MOV    DI,OFFSET UPDNLOAD_COM    ;DI-> 1st char of string
  3202.         STOSB                ;Store AL in string
  3203. MUC_RET:
  3204.         POPF                ;Restore registers & flags
  3205.         POP    SI
  3206.         POP    DI
  3207.         POP    ES
  3208.         POP    DS
  3209.         POP    CX
  3210.         POP    AX
  3211.         RET
  3212. MAKE_UP_COM    ENDP
  3213.  
  3214. ;----------------------------------------------------------------------
  3215. ; Creates the download command string that the REMOTE computer EXECS    
  3216. ;----------------------------------------------------------------------
  3217. MAKE_DN_COM    PROC    NEAR
  3218.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  3219.         PUSH    AX            ;Store registers
  3220.         PUSH    CX
  3221.         PUSH    DS
  3222.         PUSH    ES
  3223.         PUSH    DI
  3224.         PUSH    SI
  3225.         PUSHF
  3226.         PUSH    CS
  3227.         PUSH    CS
  3228.         POP    DS            ;DS -> CS
  3229.         POP    ES            ;ES -> CS
  3230.         CLD                ;Forward direction flag
  3231.         MOV    DI,OFFSET UPDNLOAD_COM    ;DI -> Download command string
  3232.         ADD    DI,10D            ;DI -> 11th char of command
  3233.         MOV    AL,SPACE        ;Reset command w/ blanks
  3234.         MOV    CX,89D            ; 89 of them...
  3235. MDC_10:
  3236.         STOSB                ;Store the blank in command
  3237.         LOOP    MDC_10            ;56 chars. complete ?
  3238.         SUB    DI,89D            ;Reset DI to 11th char.
  3239.         MOV    SI,OFFSET REMOTE_COM    ;SI -> (C)OMx
  3240.         MOV    CX,4D            ;Transfer COMx to com. line
  3241. MDC_20:
  3242.         LODSB                ;Pick off a char into AL
  3243.         STOSB                ;Move AL into command
  3244.         LOOP    MDC_20            ;All 4 chars copied ?
  3245.         MOV    AL,SPACE         ;Move a blank in after COMx
  3246.         STOSB                ;Store blank
  3247.         CMP    PATH_LENGTH,0        ;Does target directory exist?
  3248.         JE    MDC_40            ;No, skip target dir. copy
  3249.         MOV    SI,OFFSET PATH_STRING    ;Yes, SI -> 1st char of dir.
  3250.         MOV    CX,PATH_LENGTH        ;CX = length of path string
  3251. MDC_30:
  3252.         LODSB                ;Pick off one char
  3253.         STOSB                ;Store char in command line
  3254.         LOOP    MDC_30            ;All chars. copied ?
  3255.         MOV    AL,SPACE         ;Move in a blank after dir.
  3256.         STOSB                ;Store blank in line
  3257. MDC_40:
  3258.         MOV    SI,OFFSET PARM_STRING    ;SI -> 1st char of parm 
  3259.         ADD    SI,3D            ;SI -> 4th char of parm
  3260.         MOV    CX,5D            ;Move in last 5 characters
  3261. MDC_50:
  3262.         LODSB                ;Pick off one char.
  3263.         STOSB                ;Copy char in command
  3264.         LOOP    MDC_50            ;All 6 chars copied ?
  3265. MDC_60:                     
  3266.         MOV    AL,CR            ;Carriage return
  3267.         STOSB
  3268.         MOV    AL,0            ;End string with a 0
  3269.         STOSB
  3270. ;
  3271. ; Length of download_com must be inserted in the first character of the
  3272. ; string ("?/c zcopy..."), therefore the length must be determined.
  3273. ;
  3274.         MOV    SI,OFFSET UPDNLOAD_COM  ;SI-> 1st char of string
  3275.         CALL    GET_STRING_LEN        ;CX = Length of string
  3276.         MOV    AL,CL            ;Ready AL for STOSB instruct.
  3277.         MOV    DI,OFFSET UPDNLOAD_COM  ;DI-> 1st char of string
  3278.         STOSB                ;Store al in string
  3279. MDC_RET:
  3280.         POPF                ;Restore registers
  3281.         POP    SI
  3282.         POP    DI
  3283.         POP    ES
  3284.         POP    DS
  3285.         POP    CX
  3286.         POP    AX
  3287.         RET
  3288. MAKE_DN_COM    ENDP
  3289.  
  3290. ;----------------------------------------------------------------------
  3291. ; Get string length determines the length of the string that DS:SI is
  3292. ; pointing to.  The length is returned in the CX register.
  3293. ; Input - DS:SI points to the first character of the associated string.
  3294. ; Output - CX = Length of the string.
  3295. ; Changes - CX 
  3296. ;----------------------------------------------------------------------
  3297. GET_STRING_LEN    PROC    NEAR
  3298.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  3299.         PUSH    AX            ;Store registers
  3300.         PUSH    SI
  3301.         PUSHF
  3302.         CLD                ;Go forward in variables
  3303.         XOR    CX,CX            ;Reset CX (counter) to zero
  3304. GSL_10:                
  3305.         LODSB                ;Pick off one character
  3306.         OR    AL,AL            ;Is the character a zero ?
  3307.         JZ    GSL_20            ;Yes, return w/ length = CX
  3308.         INC    CX            ;No... bump character counter
  3309.         JMP    GSL_10            ;Get another character
  3310. GSL_20:
  3311.         POPF                ;Restore registers
  3312.         POP    SI
  3313.         POP    AX    
  3314.         RET
  3315. GET_STRING_LEN    ENDP
  3316.  
  3317. ;---------------------------------------------------------------------- 
  3318. ; Get current cursor position
  3319. ; Input - Nothing
  3320. ; Output - DX contains current cursor position
  3321. ; Changes - DX
  3322. ;---------------------------------------------------------------------- 
  3323. GET_CURSOR    PROC    NEAR
  3324.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  3325.         PUSH    AX            ;Push registers
  3326.         PUSH    BX
  3327.         MOV    BH,0            ;First page
  3328.         MOV    AH,3
  3329.         INT    10H            ;DOS call
  3330.         POP    BX            ;Restore registers
  3331.         POP    AX
  3332.         RET
  3333. GET_CURSOR    ENDP
  3334.  
  3335. ;--------------------------------------------------------------------    
  3336. ; Places cursor in the DX position.                    
  3337. ; Input - DX                                
  3338. ; Output - Cursor placement                    
  3339. ; Changes - Nothing                            
  3340. ;--------------------------------------------------------------------    
  3341. PUT_CURSOR    PROC    NEAR
  3342.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  3343.         PUSH    AX            ;Push registers
  3344.         PUSH    BX
  3345.         MOV    AH,2
  3346.         MOV    BH,0            ;First page
  3347.         INT    10H            ;DOS call
  3348.         POP    BX            ;Restore registers
  3349.         POP    AX
  3350.         RET
  3351. PUT_CURSOR    ENDP
  3352.  
  3353. ;--------------------------------------------------------------------  
  3354. ; Inputs a character string from the keyboard.    Characters will be     
  3355. ; accepted until the user presses the return, ESC or CX chars. have    
  3356. ; been received from keyboard.                            
  3357. ; Input - ES:DI Points to the buffer that is to receive the string.    
  3358. ;      CX    Contains the length of the input buffer.           
  3359. ; Output -CX    Contains the actual length of the character string.    
  3360. ;      AX    Contains the last keystroke                   
  3361. ;      The specified buffer contains the character string that was  
  3362. ;      entered.                               
  3363. ;--------------------------------------------------------------------- 
  3364. GETSTRING    PROC    NEAR                           
  3365.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING           
  3366.         PUSH    BX
  3367.         PUSH    DI            ;Store Registers
  3368.         PUSH    DX
  3369.         PUSHF
  3370.         CLD                ;Direction Flag Forward
  3371.         XOR    BH,BH            ;Screen page 0
  3372.         XOR    DX,DX            ;Reset character counter
  3373. GS_10:
  3374.         XOR    AH,AH            ;Function 0 -INT16H- Read key
  3375.         INT    16H            ;Read character from keys
  3376.         CMP    AL,CR            ;Carriage Return ?
  3377.         JE    GS_30            ;Yes
  3378.         CMP    AL,ESC_KEY        ;Escape key ?
  3379.         JE    GS_30            ;Yes
  3380.         CMP    AL,BS            ;Back space ?
  3381.         JNE    GS_14            ;No
  3382.         CMP    DX,0            ;Yes, but 1st char. ?
  3383.         JE    GS_10            ;Yes, so skip BS & get a key
  3384. GS_14:
  3385.         STOSB                ;No... Store Character
  3386.         INC    DX            ;Bump character counter
  3387.         MOV    AH,14            ;Function 14 -INT10H- 
  3388.         INT    10H            ;Display character
  3389.         CMP    AL,BS            ;Was last char a backspace ? 
  3390.         JNE    GS_20            ;No
  3391. GS_15:
  3392.         SUB    DX,2            ;Decrement char count twice
  3393.         SUB    DI,2            ;Move PTR back 2 spaces
  3394.         ADD    CX,2            ;Move in two spaces
  3395.         MOV    AH,14            ;Display character interrupt
  3396.         MOV    AL,SPACE        ;Space
  3397.         INT    10H            ;Display character
  3398.         MOV    AH,14            ;Display character interrupt
  3399.         MOV    AL,BS            ;Backspace
  3400.         INT    10H            ;Display character
  3401. GS_20:
  3402.         LOOP    GS_10            ;Size = # of characters
  3403. GS_30:
  3404.         MOV    CX,DX            ;Save # of chars. in CX
  3405.         POPF                ;Restore Registers
  3406.         POP    DX
  3407.         POP    DI
  3408.         POP    BX
  3409.         RET
  3410. GETSTRING    ENDP
  3411.  
  3412. ;------------------------------------------------------------  
  3413. ; Input - DS:SI must point to the 1st char of the string to be
  3414. ;      sent to the host computer.
  3415. ; Output - The entire string is sent to the host computer until
  3416. ;       a ZERO (end of string) is found.
  3417. ; Changes - SI,AL                          
  3418. ;------------------------------------------------------------ 
  3419. SEND_STRING    PROC    NEAR                       
  3420.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING           
  3421.         PUSHF                ;Store Direction Flag
  3422.         CLD
  3423. SZ_10:
  3424.         LODSB                ;Get AL
  3425.         CMP    AL,0            ;Done with string ?
  3426.         JE    SZ_EXIT         ;Yes...
  3427.         CALL    GET_SEND_CODE        ;No...get & send scan
  3428.         JMP    SZ_10            ;Repeat until done
  3429. SZ_EXIT:
  3430.         POPF                ;Restore Direction Flag
  3431.         RET
  3432. SEND_STRING    ENDP
  3433.  
  3434. ;------------------------------------------------------------ 
  3435. ; Input - AL contains the ASCII code of the character to be 
  3436. ;      sent to the host computer.
  3437. ; Output - AX is sent to the host computer where 
  3438. ;        AL is ASCII code 
  3439. ;        AH is the associated scan code for the ASCII code
  3440. ; Changes - Nothing
  3441. ;------------------------------------------------------------ 
  3442. GET_SEND_CODE    PROC    NEAR                      
  3443.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING         
  3444.         PUSH    AX            ;Store Registers
  3445.         PUSH    BX
  3446.         PUSH    CX
  3447.         PUSH    SI
  3448.         PUSHF
  3449.         CMP    AL,'a'            ;Small Case letter ?
  3450.         JL    GSC_10            ;No ....
  3451.         CMP    AL,'z'
  3452.         JG    GSC_10            ;No ....
  3453.         SUB    AL,32D            ;Yes ....
  3454. GSC_10:
  3455.         MOV    BL,AL            ;Save ASCII code
  3456.         MOV    CX,0            ;Reset counter into var.
  3457.         MOV    SI,OFFSET ASCII_CODE    ;DS:SI -> ASCII variable
  3458.         CLD                ;Forward
  3459. GSC_20:
  3460.         CMP    CX,70D            ;Invalid ASCII ?
  3461.         JE    GSC_EXIT        ;Yes...
  3462.         INC    CX            ;Bump counter
  3463.         LODSB                ;AL = next char in var.
  3464.         CMP    AL,BL            ;Find correct offset ?
  3465.         JNE    GSC_20            ;No...
  3466. GSC_30:                     ;Yes... so bump that far
  3467.         MOV    SI,OFFSET SCAN_CODE    ;into scan_code var and
  3468.         CLD                ;pick off that scan_code.
  3469. GSC_40:
  3470.         LODSB
  3471.         LOOP    GSC_40
  3472. GSC_50:
  3473.         MOV    AH,AL            ;AH = scan-code
  3474.         MOV    AL,BL            ;AL = ASCII code
  3475.         CALL    SEND_KEYSTROKE        ;Send AX
  3476. GSC_EXIT:
  3477.         POPF                ;Restore registers
  3478.         POP    SI
  3479.         POP    CX
  3480.         POP    BX
  3481.         POP    AX
  3482.         RET
  3483. GET_SEND_CODE    ENDP
  3484.  
  3485. ;-----------------------------------------------------------------
  3486. ; Execute ZCOPY (upload/download) or shell to DOS and return to
  3487. ; the calling program.
  3488. ;-----------------------------------------------------------------
  3489. EXEC_ZCOPY    PROC    NEAR
  3490.         CMP    BYTE PTR NOEXEC,0FFH
  3491.         JNZ    EZ_10
  3492.         JMP    EZ_EXIT
  3493. EZ_10:
  3494.         PUSH    AX            ;Store all registers
  3495.         PUSH    BX
  3496.         PUSH    CX
  3497.         PUSH    DX
  3498.         PUSH    SI
  3499.         PUSH    DI
  3500.         PUSH    DS
  3501.         PUSH    ES
  3502.         PUSH    BP
  3503.         PUSH    CS
  3504.         PUSH    CS
  3505.         POP    DS
  3506.         POP    ES
  3507.         CMP    EXEC_VAL,1D        ;Shelling to DOS ?
  3508.         JE    EZ_20            ;Yes, display shell prompt
  3509.         CMP    EXEC_VAL,2D        ;Downloading from host ?
  3510.         JE    EZ_30            ;Yes, display transfer prompt
  3511.         CMP    EXEC_VAL,3D        ;Uploading from host ?
  3512.         JE    EZ_30            ;Yes, display transfer prompt
  3513.         JMP    EZ_60            ;EXEC_VAL has wrong value !
  3514. EZ_20:
  3515.         MOV    AX,OFFSET NUL_TAIL    ;Shell to DOS
  3516.         MOV    SI,OFFSET SHELL_PROMPT    ;Notify user of shell
  3517.         JMP    EZ_40                
  3518. EZ_30:
  3519.         MOV    AX,OFFSET UPDNLOAD_COM      ;Uploading
  3520.         MOV    SI,OFFSET TRANSFER_PROMPT ;Notify transferring
  3521. EZ_40:
  3522.         MOV    PAR_BLK+2,AX        ;EXEC
  3523.         CALL    CLEAR_SCREEN        ;Clear remote screen
  3524.         CALL    GET_STRING_LEN        ;Get string length of DS:SI
  3525.         PUSH    ES            ;Store registers & flags
  3526.         PUSH    DI
  3527.         PUSHF                ;Store flag
  3528.         MOV    AX,VIDEO_SEGMENT    ;AX->1st char of video segment
  3529.         MOV    ES,AX            ;ES->1st char of video segment
  3530.         XOR    DI,DI            ;ES:DI-> 1st char of video seg
  3531.         CLD                ;Forward in video segment
  3532. EZ_50:
  3533.         LODSB                ;Pick off char in string
  3534.         CALL    PUT_VIDEO_DATA        ; and place in video segment
  3535.         MOV    AL,70H            ;Place reverse video
  3536.         CALL    PUT_VIDEO_DATA        ; in video segment 
  3537.         LOOP    EZ_50            ;All characters displayed ?
  3538.         POPF                ;Restore flags
  3539.         POP    DI            ;Restore registers
  3540.         POP    ES
  3541.         MOV    DH,2D            ;Row 2
  3542.         XOR    DL,DL            ;Col 0
  3543.         CALL    PUT_CURSOR        ;Place cursor on screen
  3544.         CALL    SET_ENV
  3545.         CMP    BYTE PTR NOEXEC,0FFH
  3546.         JZ    EZ_60
  3547.         PUSH    DS
  3548.         PUSH    ES
  3549.         MOV    OLD_SS,SS
  3550.         MOV    OLD_SP,SP
  3551.         MOV    BX,OFFSET PAR_BLK
  3552.         LDS    DX,CS:COMSPC
  3553.         MOV    AX,4B00H
  3554.         INT    21H
  3555. ;
  3556. ; return from DOS exec
  3557. ;
  3558.         MOV    SS,CS:OLD_SS
  3559.         MOV    SP,CS:OLD_SP
  3560.         MOV    ES,CS:PAR_BLK
  3561.         MOV    AH,49H
  3562.         INT    21H
  3563.         POP    ES
  3564.         POP    DS
  3565. EZ_60:
  3566.         POP    BP
  3567.         POP    ES
  3568.         POP    DS
  3569.         POP    DI
  3570.         POP    SI
  3571.         POP    DX
  3572.         POP    CX
  3573.         POP    BX
  3574.         POP    AX
  3575. EZ_EXIT:    
  3576.         RET
  3577. EXEC_ZCOPY    ENDP
  3578.  
  3579. ;-----------------------------------------------------------------------
  3580. ;  Find the string pointed to by DS:SI in the segment pointed to by ES
  3581. ;      ES:0000 is assumed to contain null terminated stings.
  3582. ;  Input - ES points to environment segment
  3583. ;       SI points to search string
  3584. ;  Output - Zero set - could not locate string
  3585. ;        Zero reset - found the string, ES:DI points to end of string
  3586. ;             found.  DI is also count of characters up to 
  3587. ;             end of string.
  3588. ;  Changes - 
  3589. ;-----------------------------------------------------------------------
  3590. FIND_SI     PROC    NEAR
  3591.         XOR    DI,DI            ;Zero environment pointer
  3592. FNDSI1:     MOV    BX,SI            ;Save the source string
  3593.         CMP    BYTE PTR ES:[DI],00    ;End of environment space?
  3594.         JNZ    FNDSI2            ; no
  3595.         RET                ; yes, return with zero set
  3596. FNDSI2:
  3597.         MOV    AL,[BX]            ;Get source string character
  3598.         OR    AL,AL            ;End of string?
  3599.         JZ    FNDSI4            ; yes
  3600.         CMP    AL,ES:[DI]        ; no, Same as environment char?
  3601.         JNZ    FNDSI3            ; no, string doesn't match
  3602.         INC    BX            ; yes, check the next char
  3603.         INC    DI            ; in both strings
  3604.         JMP    FNDSI2
  3605. FNDSI3:
  3606.         XOR    AL,AL            ;Null string terminator
  3607.         MOV    CX,-0001        ;Make sure to find string end
  3608.         CLD
  3609.         REPNZ    SCASB            ;Find the end of this string
  3610.         JMP    FNDSI1            ;Test the next string
  3611. FNDSI4:
  3612.         XOR    AX,AX            ;Located the string
  3613.         INC    AX            ;Reset the zero flag
  3614.         RET
  3615. FIND_SI     ENDP
  3616.  
  3617. ;-----------------------------------------------------------------
  3618. ;    SET NEW ENVIRONMENT
  3619. ;
  3620. ;-----------------------------------------------------------------
  3621.  
  3622. SET_ENV     PROC    NEAR
  3623.         PUSH    DS
  3624.         PUSH    ES
  3625.         MOV    ES,DS:[002CH]        ;Environment segment pointer
  3626.         MOV    SI,OFFSET PMTSTR    ;Pointer to "PROMPT="
  3627.         CALL    FIND_SI            ;Is "PROMPT=" in environment?
  3628.         JNZ    GOTPMT            ; yes
  3629.         XOR    DI,DI            ; no, set length to 0
  3630. ;
  3631. ;  DI = number of characters in environment to end of "PROMPT=" string.
  3632. ;
  3633. GOTPMT:
  3634.         MOV    BX,DI            ;Save the count
  3635.         XOR    DI,DI
  3636.         MOV    AX,DI
  3637.         MOV    CX,0FFFFH
  3638.         CLD
  3639.         REPNZ    SCASW            ;Locate the end of the string
  3640.         MOV    AX,PMTLGT
  3641.         ADD    AX,DI
  3642.         CMP    BX,0000
  3643.         JNZ    PMTHER
  3644.         ADD    AX,(OFFSET PCRSTR) - (OFFSET DFTPMT)
  3645. PMTHER:
  3646.         MOV    CL,04
  3647.         SHR    AX,CL
  3648.         INC    AX
  3649.         SUB    DI,BX
  3650.         PUSH    DI
  3651.  
  3652.         PUSH    BX
  3653.         MOV    BX,AX            ;number of paragraphs request
  3654.         MOV    AH,48H            ;malloc
  3655.         INT    21H
  3656.         JNC    NOERR
  3657.         MOV    BYTE PTR NOEXEC,0FFH
  3658.  
  3659. NOERR:        MOV    PAR_BLK,AX        ;segment to malloc
  3660.         MOV    ES,AX            ;segment to malloc
  3661.         XOR    DI,DI
  3662.         CLD
  3663.         POP    CX
  3664.         CMP    CX,0000
  3665.         JNZ    DOITAL
  3666.         MOV    CX,PMTLGT
  3667.         MOV    WORD PTR PMTLGT,0000
  3668.         ADD    CX,(OFFSET PCRSTR) - (OFFSET DFTPMT)
  3669.         MOV    SI,OFFSET DFTPMT
  3670.         REP    MOVSB
  3671.         MOV    SI,OFFSET GODPMT
  3672.         MOV    CX,(OFFSET PMTSTR) - (OFFSET GODPMT)
  3673.         REP    MOVSB
  3674. ;
  3675. ;    FROM ADD TO USERS PROMPT
  3676. ;
  3677. DOITAL:
  3678.         MOV    AX,DS:[002CH]
  3679.         MOV    DS,AX
  3680.         XOR    SI,SI
  3681.         JCXZ    PMTDON
  3682.         REP    MOVSB
  3683. ;
  3684. ;    IF NO PROMPT=', NEW PROMPT STORED AND WHOLE ENV STORED NEXT
  3685. ;
  3686. PMTDON:
  3687.         PUSH    DS
  3688.         PUSH    SI
  3689.         PUSH    CS
  3690.         POP    DS
  3691.         MOV    SI,OFFSET PCRSTR
  3692.         MOV    CX,PMTLGT
  3693.         JCXZ    NOPMT
  3694.         REP    MOVSB
  3695. ;
  3696. ;    ANY PROMPT STORED?
  3697. ;
  3698. NOPMT:
  3699.         POP    SI
  3700.         POP    DS
  3701.         POP    CX
  3702.         REP    MOVSB
  3703.         POP    ES
  3704.         POP    DS
  3705.         RET
  3706. SET_ENV     ENDP
  3707.  
  3708. ;----------------------------------------------------------------------
  3709. GET_COMSPEC    PROC    NEAR
  3710.         PUSH    ES
  3711.         MOV    PAR_BLK+04,DS
  3712.         MOV    AX,DS:[002CH]
  3713.         MOV    PAR_BLK,AX
  3714.         MOV    ES,AX
  3715.         MOV    SI,OFFSET COM_VAR
  3716.         CALL    FIND_SI
  3717.         MOV    CS:COM_SEG,ES
  3718.         MOV    CS:COM_OFS,DI
  3719.         JNZ    NO_FND
  3720.         MOV    BYTE PTR NOEXEC,0FFH
  3721. NO_FND:
  3722.         POP    ES
  3723.         RET
  3724. GET_COMSPEC    ENDP
  3725.  
  3726. ;----------------------------------------------------------------------
  3727. ; Switch ES and DS
  3728. ; Input - Nothing
  3729. ; Output - ES is in DS and DS is in ES
  3730. ; Changes - ES, DS
  3731. ;----------------------------------------------------------------------
  3732. SWITCH_DS_ES    PROC    NEAR
  3733.         PUSH    ES            ;Push ES
  3734.         PUSH    DS            ;Push DS
  3735.         POP    ES            ;Switch ES
  3736.         POP    DS            ;with DS
  3737.         RET
  3738. SWITCH_DS_ES    ENDP
  3739.  
  3740. ;----------------------------------------------------------------------
  3741. ; Put the keystroke data into the output buffer to be sent to unattended
  3742. ; system
  3743. ; Input - AX - keystroke data
  3744. ; Output - Nothing
  3745. ; Changes - Nothing
  3746. ;----------------------------------------------------------------------
  3747. SEND_KEYSTROKE    PROC    NEAR
  3748.     ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  3749.         PUSH    AX            ;Save it
  3750.         MOV    AH,1            ;Use the output buffer
  3751.         MOV    AL,0FEH         ;Sync byte, to expect key data
  3752.         CALL    PUT_BUFF_DATA        ;Put AL into the output buffer
  3753.         POP    AX            ;Get AL back
  3754.         PUSH    AX            ;Save AH
  3755.         MOV    AH,1            ;Use the output buffer
  3756.         CALL    PUT_BUFF_DATA        ;Put ASCII code in out buffer
  3757.         POP    AX            ;Get AH back
  3758.         PUSH    AX            ;Save keystroke
  3759.         MOV    AL,AH            ;Move it to AL
  3760.         MOV    AH,1            ;Use the output buffer
  3761.         CALL    PUT_BUFF_DATA        ;Put scan code in out buffer
  3762.         POP    AX            ;Restore keystroke
  3763.         RET
  3764. SEND_KEYSTROKE    ENDP
  3765.  
  3766. ;======================================================================
  3767. LAST_BYTE    EQU    $
  3768. CSEG        ENDS
  3769.         END    START
  3770.  
  3771.