home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / comm / pcremote.zip / PCREMOTE.ASM next >
Assembly Source File  |  1990-01-04  |  64KB  |  1,756 lines

  1.         TITLE    PCREMOTE - Unattended Computer Access - 1989 by Terry Lahman
  2.         PAGE    60,132
  3. ;======================================================================
  4. ;
  5. ;  PCREMOTE - 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:    PCREMOTE [ /M ] [ /2 ] [ /F ] [ /D ]
  13. ;
  14. ;======================================================================
  15. CSEG    SEGMENT PARA PUBLIC 'CODE'
  16.         ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  17.  
  18. BS                EQU     8
  19. CR                EQU     13
  20. LF                EQU     10
  21. SPACE            EQU     32
  22.  
  23. ;----------------------------------------------------------------------
  24. ;  Start of code
  25. ;----------------------------------------------------------------------
  26.                 ORG     100H                    ;Starting offset for .com
  27. START:            JMP     INITIALIZE                ;Jump over resident code
  28.  
  29. ;----------------------------------------------------------------------
  30. ;  Data storage
  31. ;----------------------------------------------------------------------
  32.  
  33. COPYRIGHT        DB        "PCREMOTE Version 1.0 (c) 1989 Ziff Communications Co."
  34.                 DB        CR,LF,"PC Magazine ",254," by Terry Lahman",CR,LF,"$",26
  35. CONNECT_FLAG    DB        0                        ;0=not connected
  36.                                                 ;1=connected to manned system
  37. ACT_FLAG        DB        0                        ;0=unattended prog not active
  38.                                                 ;1=unattended program is active
  39.                                                 ; do not run again
  40. OLDINT_8        DW        0,0                     ;Old timer vector
  41. MANNED_FLAG     DB        0                        ;0=Operate in unattended mode
  42.                                                 ;1=Operate in manned mode
  43. COMM_FLAG        DB        0                        ;0=Use COM1
  44.                                                 ;1=Use COM2
  45. COMM_PORT        DW        0                        ;Comm port address
  46. COMM_INT_STA    DB        0                        ;Comm port interrupt status
  47.                                                 ;0=not transmitting data
  48.                                                 ;1=transmitting data
  49. SPEED_FLAG        DB        0                        ;0=Use 1200 baud
  50.                                                 ;1=Use 2400 baud
  51. DESNOW_FLAG     DB        0                        ;0=Do not use desnow code
  52.                                                 ;1=Use desnow code
  53. VIDEO_COPY        DW        0                        ;Address of video ram copy
  54. VIDEO_SEGMENT    DW        0                        ;Segment register for vid ram
  55. SHIFT_STATUS    DB        0                        ;Current status of shift byte
  56. STACK_TOP        DW        INITIALIZE+256D         ;Top of stack for unattended
  57. OLD_SS            DW        0                        ;Old stack segment
  58. OLD_SP            DW        0                        ;Old stack pointer
  59. TEMP_REG        DW        0                        ;Temp storage for register
  60. CURSOR_POSITION DW        0                        ;Old cursor position
  61. VID_RAM_OFFSET    DW        0                        ;Current compare offset
  62. ASCII_FLAG        DB        0                        ;0=no data is pending
  63.                                                 ;1=received a FE
  64.                                                 ;2=received ASCII char
  65.                                                 ;4=received scan code
  66. SHIFT_FLAG        DB        0                        ;0=no data is pending
  67.                                                 ;1=received a FD
  68. KEY_ONE         DB        0                        ;ASCII char received
  69. KEY_TWO         DB        0                        ;Scan code received
  70. BAUD_RATE        DB        0,60H                    ;1200 BAUD divisor MSB LSB
  71.                 DB        0,30H                    ;2400 BAUD divisor MSB LSB
  72. IN_BUFF_SIZE    EQU     512D                    ;Size for input buffer
  73. OUT_BUFF_SIZE    EQU     512D                    ;Size for output buffer
  74. IN_BUFF_HEAD    DW        ?                        ;Pointer to input buffer head
  75. IN_BUFF_TAIL    DW        ?                        ;Pointer to input buffer tail
  76. IN_BUFF_BEGIN    DW        ?                        ;Pointer to input buffer begin
  77. IN_BUFF_END     DW        ?                        ;Pointer to input buffer end
  78. OUT_BUFF_HEAD    DW        ?                        ;Pointer to output buffer head
  79. OUT_BUFF_TAIL    DW        ?                        ;Pointer to output buffer tail
  80. OUT_BUFF_BEGIN    DW        ?                        ;Pointer to output buffer begin
  81. OUT_BUFF_END    DW        ?                        ;Pointer to output buffer end
  82. BLOCK_SIZE        EQU     16D                     ;Block transfer size in words
  83. BLOCK_SIZEX2    EQU     BLOCK_SIZE*2            ;Block transfer size in bytes
  84. BLOCK_COUNT     DB        ?                        ;Block number being processed
  85. BLOCK_POINTER    DW        0                        ;Points to current video block
  86. TEMP_VIDEO_PTR    DW        ?                        ;Pointer to temp video storage
  87. CR_COUNT        DB        ?                        ;Number of CRs for speed sync
  88. MODEM_ATTENTION DB        CR,"AT",CR,0
  89. MODEM_SETUP1    DB        "ATE0 S12=40 Q0 V0 X1 S0=0",CR,0    ;Manned
  90. MODEM_SETUP2    DB        "ATE0 S12=40 Q1 S0=2",CR,0            ;Unattended
  91. MODEM_SETUP3    DB        "AT&C1",CR,0            ;Enable DCD on 2400 baud modem
  92. MODEM_HANGUP    DB        "ATH0",CR,0
  93. MODEM_ESCAPE    DB        "+++",0
  94. TONE_DIAL        DB        "ATDT",0                ;Tone dial command
  95. PASS_MESSAGE    DB        "Enter password:",0     ;Enter password message
  96. PASSWORD_SIZE    DW        EXTRA_PW_SPACE-PASSWORD
  97. PASSWORD        DB        "PC MAGAZINE"
  98. EXTRA_PW_SPACE    DB        20-(EXTRA_PW_SPACE-PASSWORD) DUP(?)
  99. PASSWORD_BUFFER DB        20 DUP(?)
  100. EXIT_CODE        DB        0,45D                    ;alt-x, code to exit program
  101.  
  102. ;======================================================================
  103. ;  Interrupt handlers.    Interrupt 8 is used in unattended mode only.
  104. ;  The communications interrupt is used in both modes.
  105. ;======================================================================
  106. ;----------------------------------------------------------------------
  107. ;  Interrupt 8 handling routine.  If program is already active do not run.
  108. ;  Run connect unattended if not connected, otherwise run unattended.
  109. ;----------------------------------------------------------------------
  110. INT8            PROC    NEAR
  111.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  112.                 PUSH    DS                        ;Save data segment
  113.                 PUSH    CS                        ;Set data segment to code seg
  114.                 POP     DS
  115.                 PUSHF                            ;Call old int 8
  116.                 CALL    DWORD PTR OLDINT_8
  117. I8_10:
  118.                 CLI                             ;Disable interrupts
  119.                 CMP     BYTE PTR ACT_FLAG,0     ;Check for program active
  120.                 JNZ     I8_EXIT                 ;Exit if progam is active
  121.                 INC     BYTE PTR ACT_FLAG        ;Set program active flag
  122.                 STI                             ;Enable interrupts
  123.                 CALL    SET_STACK                ;Create stack & save registers
  124.                 CMP     BYTE PTR CONNECT_FLAG,0 ;Connected to manned?
  125.                 JNZ     I8_20                    ;Yes, then run unattended
  126.                 CALL    CONNECT_UNATTENDED        ;No, check for connection
  127.                 JMP     I8_30
  128. I8_20:
  129.                 CALL    UNATTENDED                ;Run unattended
  130. I8_30:
  131.                 CALL    RESET_STACK             ;Restore registers & stack
  132.                 DEC     BYTE PTR ACT_FLAG        ;Clear program active flag
  133. I8_EXIT:
  134.                 STI                             ;Enable interrupts
  135.                 POP     DS                        ;Restore data segment
  136.                 IRET
  137. INT8            ENDP
  138.  
  139. ;----------------------------------------------------------------------
  140. ;  Interrupt handling routine for communications interrupt.  Provides
  141. ;  interrupt driven I/O.  Transmit or receive a character.
  142. ;----------------------------------------------------------------------
  143. INT_COMM        PROC    NEAR
  144.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  145.                 PUSH    DS                        ;Save data segment
  146.                 PUSH    DX                        ;Save registers
  147.                 PUSH    BX
  148.                 PUSH    AX
  149.                 PUSH    CS                        ;Set data segment to code seg.
  150.                 POP     DS
  151.                 MOV     DX,COMM_PORT            ;Get port base address
  152.                 INC     DX                        ;Point to int. id reg.
  153.                 INC     DX
  154.                 IN        AL,DX                    ;Get the interrupt id byte
  155. IC_10:
  156.                 CMP     AL,2                    ;Transmit empty int?
  157.                 JZ        IC_40                    ;Yes transmit a byte
  158. ;
  159. ;        received data, get it and store in buffer
  160. ;
  161.                 DEC     DX                        ;Port base address
  162.                 DEC     DX
  163.                 IN        AL,DX                    ;Get data from receive register
  164.                 MOV     BX,IN_BUFF_TAIL         ;Get the buffer tail pointer
  165.                 MOV     [BX],AL                 ;Store the data in buffer
  166.                 INC     BX                        ;Point to next data storage
  167.                 CMP     IN_BUFF_END,BX            ;Beyond end of buffer area?
  168.                 JNE     IC_20                    ;No, then don't reset
  169.                 MOV     BX,IN_BUFF_BEGIN        ;Yes, reset to buffer begin
  170. IC_20:
  171.                 CMP     BX,IN_BUFF_HEAD         ;Test for buffer full
  172.                 JE        IC_30                    ;If so,don't change ptr ,sorry
  173.                 MOV     IN_BUFF_TAIL,BX         ;Save new tail pointer
  174. IC_30:
  175.                 JMP     IC_70
  176. ;
  177. ;        transmit buffer empty, send a byte
  178. ;
  179. IC_40:
  180.                 DEC     DX                        ;Port base address
  181.                 DEC     DX
  182.                 MOV     BX,OUT_BUFF_HEAD        ;Get the buffer head pointer
  183.                 CMP     BX,OUT_BUFF_TAIL        ;Test for data in buffer
  184.                 JE        IC_60                    ;If the same, no data so exit
  185.                 MOV     AL,[BX]                 ;Get the data
  186.                 INC     BX                        ;Point to next data in buffer
  187.                 CMP     OUT_BUFF_END,BX         ;Beyond end of buffer area?
  188.                 JNE     IC_50                    ;No, then don't reset
  189.                 MOV     BX,OUT_BUFF_BEGIN        ;Yes, reset to buffer begin
  190. IC_50:
  191.                 MOV     OUT_BUFF_HEAD,BX        ;Save new head pointer
  192.                 OUT     DX,AL                    ;Send the data out the port
  193.                 JMP     IC_70                    ;Check for request pending
  194. IC_60:
  195.                 MOV     BYTE PTR COMM_INT_STA,0 ;Reset transmitting data flag
  196. IC_70:
  197.                 INC     DX                        ;Point to int. id reg.
  198.                 INC     DX
  199.                 IN        AL,DX                    ;Get the interrupt id byte
  200.                 TEST    AL,1                    ;Request pending?
  201.                 JZ        IC_10                    ;Yes, then process
  202. IC_EXIT:
  203.                 MOV     AL,20H                    ;Reset 8259
  204.                 OUT     20H,AL
  205.                 STI                             ;Enable interrupts
  206.                 POP     AX                        ;Restore registers
  207.                 POP     BX
  208.                 POP     DX
  209.                 POP     DS                        ;Restore data segment
  210.                 IRET
  211. INT_COMM        ENDP
  212.  
  213. ;----------------------------------------------------------------------
  214. ;  Create stack area and save all registers.
  215. ;----------------------------------------------------------------------
  216. SET_STACK        PROC    NEAR
  217.                 ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  218.                 MOV     TEMP_REG,BX             ;Save BX
  219.                 POP     BX                        ;Save the return address
  220.                 PUSH    AX                        ;Save AX
  221. ;
  222. ;        make my own stack
  223. ;
  224.                 CLI                             ;Disable interrupts
  225.                 MOV     AX,SS                    ;Put old stack segment in AX
  226.                 MOV     OLD_SS,AX                ;And save it
  227.                 MOV     AX,SP                    ;Put old stack pointer in AX
  228.                 MOV     OLD_SP,AX                ;And save it
  229.                 MOV     AX,CS                    ;Get current segment
  230.                 MOV     SS,AX                    ;And put into stack segment
  231.                 MOV     AX,STACK_TOP            ;Get top of stack address
  232.                 MOV     SP,AX                    ;And put into stack pointer
  233.                 STI                             ;Enable interrupts
  234. ;
  235. ;        save all the registers on the stack
  236. ;
  237.                 PUSH    CX
  238.                 PUSH    DX
  239.                 PUSH    SI
  240.                 PUSH    DI
  241.                 PUSH    DS
  242.                 PUSH    ES
  243.                 PUSH    BP
  244.                 MOV     AX,CS                    ;Get code segment
  245.                 MOV     DS,AX                    ;Set data segment to code seg
  246.                 MOV     ES,AX                    ;Set extra seg to code seg
  247.                 PUSH    BX                        ;Restore return address
  248.                 RET
  249. SET_STACK        ENDP
  250.  
  251. ;----------------------------------------------------------------------
  252. ;  Restore all registers and reset stack
  253. ;----------------------------------------------------------------------
  254. RESET_STACK     PROC    NEAR
  255.                 ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  256.                 POP     BX                        ;Save return address
  257. ;
  258. ;        restore the registers
  259. ;
  260.                 POP     BP                        ;Restore the registers
  261.                 POP     ES
  262.                 POP     DS
  263.                 POP     DI
  264.                 POP     SI
  265.                 POP     DX
  266.                 POP     CX
  267. ;
  268. ;        restore the original stack
  269. ;
  270.                 CLI                             ;Disable interrupts
  271.                 MOV     AX,OLD_SP                ;Get old stack pointer
  272.                 MOV     SP,AX                    ;And restore it
  273.                 MOV     AX,OLD_SS                ;Get old stack segment
  274.                 MOV     SS,AX                    ;And restore it
  275.                 STI                             ;Enable interrupts
  276.                 POP     AX                        ;Restore AX
  277.                 PUSH    BX                        ;Put return add back on stack
  278.                 MOV     BX,TEMP_REG             ;Restore BX
  279.  
  280.                 RET
  281. RESET_STACK     ENDP
  282.  
  283. ;======================================================================
  284. ;  The unattended routine will execute the connect routine to establish
  285. ;  a connection with the manned system.  Once connected it will execute 
  286. ;  the unattended routine to process incoming data and send any changed
  287. ;  video data to the manned system.
  288. ;======================================================================
  289.  
  290. ;----------------------------------------------------------------------
  291. ;  CONNECT_UNATTENDED - Check for ring codes, answer the phone and check
  292. ;  the password.  If correct, set connected flag.
  293. ;----------------------------------------------------------------------
  294. CONNECT_UNATTENDED PROC    NEAR
  295.         ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  296.                 MOV     BP,SP                    ;Save stack pointer for exit
  297.                 CALL    CHECK_CARRIER            ;Test for carrier present
  298.                 JNZ     CU_10                    ;Yes then check baud rate
  299.                 JMP     CU_EXIT                 ;No, then exit routine
  300. CU_10:
  301.                 CALL    CLEAR_INBUFF            ;Clear the input buffer
  302.                 XOR     AH,AH                    ;Use input buffer
  303.                 MOV     CX,10D                    ;Number of char to check for CR
  304.                 MOV     BYTE PTR CR_COUNT,5     ;Number of matches required
  305. CU_20:
  306.                 CALL    CHECK_CARRIER            ;Check for carrier loss
  307.                 JNZ     CU_30
  308.                 JMP     IP_50                    ;Carrier loss, reset and exit
  309. CU_30:
  310.                 CALL    GET_BUFF_DATA            ;Try to get data from buffer
  311.                 JNC     CU_20                    ;Wait till their is data
  312.                 CMP     AL,CR                    ;Check for CR code
  313.                 JNZ     CU_40                    ;No so skip over
  314.                 DEC     BYTE PTR CR_COUNT        ;Found a match dec count
  315.                 JZ        CU_50                    ;5 out of ten then 2400 baud
  316. CU_40:
  317.                 LOOP    CU_20                    ;Keep trying
  318.                 XOR     AL,AL                    ;No 5 out of 10, try 1200 baud
  319.                 CALL    SET_BAUD_RATE
  320.                 JMP     CU_10                    ;Now wait for CR at 1200 baud
  321. CU_50:
  322.                 MOV     BYTE PTR CONNECT_FLAG,1 ;Set connect flag
  323.                 MOV     CX,3                    ;3 tries to enter password
  324. CU_60:
  325.                 MOV     SI,OFFSET PASS_MESSAGE    ;Point to enter password mess.
  326.                 CALL    LOAD_ZSTRING            ;Load it into output buffer
  327.                 CALL    GET_PASSWORD            ;Get the password
  328.                 CALL    CHECK_PASSWORD            ;Check the password sent
  329.                 JZ        CU_70                    ;Jump if correct
  330.                 LOOP    CU_60                    ;Keep trying
  331.                 MOV     AL,1                    ;Use setup string 2
  332.                 CALL    RESET_MODEM             ;Hangup and reset modem
  333.                 JMP     CU_EXIT                 ;Done, so exit
  334. CU_70:
  335.                 MOV     AH,1                    ;Use output buffer
  336.                 XOR     AL,AL                    ;Sync byte to send
  337.                 MOV     CX,5                    ;Send 5 of them
  338. CU_80:
  339.                 CALL    PUT_BUFF_DATA            ;Send them
  340.                 LOOP    CU_80
  341. CU_EXIT:
  342.                 RET
  343. CONNECT_UNATTENDED ENDP
  344.  
  345. ;----------------------------------------------------------------------
  346. ;  Get the password from the manned system
  347. ;  Input - Nothing
  348. ;  Output - Password buffer contains password from manned system
  349. ;  Changes - DI, AX
  350. ;----------------------------------------------------------------------
  351. GET_PASSWORD    PROC    NEAR
  352.         ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  353.                 PUSH    CX                          ;Save register
  354.                 MOV     DI,OFFSET PASSWORD_BUFFER ;Point to password buffer
  355.                 MOV     CX,20D                      ;Zero buffer to clear previous
  356.                 XOR     AL,AL                      ; password
  357.                 CLD
  358.                 REP     STOSB
  359.                 MOV     DI,OFFSET PASSWORD_BUFFER ;Pointer to buffer
  360.                 MOV     CX,20D                      ;Maximum password size
  361. GP_10:
  362.                 CALL    CHECK_CARRIER            ;Check for carrier loss
  363.                 JNZ     GP_20
  364.                 JMP     IP_50                    ;Carrier loss, reset and exit
  365. GP_20:
  366.                 CALL    INPUT_PROCESSING        ;Get data & put in keybd buffer
  367.                 CALL    GET_KEYSTROKE            ;Check for keystroke
  368.                 JZ        GP_10                    ;None, so wait
  369.                 CMP     AL,60H                    ;Check for lower case
  370.                 JL        GP_30                    ;No then leave it alone
  371.                 AND     AL,5FH                    ;Convert to upper case
  372. GP_30:
  373.                 CMP     AL,CR                    ;If it is a CR then exit
  374.                 JZ        GP_EXIT
  375.                 CMP     AL,BS                    ;Is it a back space?
  376.                 JNZ     GP_40                    ;No, so save it
  377.                 INC     CX                          ;Resetcounter for BS
  378.                 CMP     DI,OFFSET PASSWORD_BUFFER ;Already at start of buffer?
  379.                 JZ        GP_60                      ;Yes, then don't backspace
  380.                 DEC     DI                        ;Backspace buffer pointer
  381.                 MOV     BYTE PTR [DI],0         ; and null the data
  382.                 JMP     GP_50
  383. GP_40:
  384.                 CLD                             ;Forward
  385.                 STOSB                            ;Save the character
  386.                 MOV     AL,'*'                    ;Echo character
  387. GP_50:
  388.                 MOV     AH,1                    ;Use output buffer
  389.                 CALL    PUT_BUFF_DATA            ; and store the character
  390. GP_60:
  391.                 LOOP    GP_10                    ;Receive up to CX characters
  392. GP_EXIT:
  393.                 POP     CX                        ;Restore register
  394.                 RET
  395. GET_PASSWORD    ENDP
  396.  
  397. ;----------------------------------------------------------------------
  398. ;  Check the password in the buffer with correct password
  399. ;  Input - Nothing
  400. ;  Output - Zero set - correct password
  401. ;            Zero reset - Wrong password
  402. ;  Changes - SI, DI
  403. ;----------------------------------------------------------------------
  404. CHECK_PASSWORD    PROC    NEAR
  405.         ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  406.                 PUSH    CX                          ;Save register
  407.                 MOV     SI,OFFSET PASSWORD_BUFFER ;Pointer to buffer
  408.                 MOV     DI,OFFSET PASSWORD          ;Pointer to password
  409.                 MOV     CX,PASSWORD_SIZE        ;Number of compares to make
  410.                 CLD                             ;Compare forward
  411.                 REPZ    CMPSB                    ;Repeat while passwords match
  412.                 POP     CX                        ;Restore register
  413.                 RET
  414. CHECK_PASSWORD    ENDP
  415.  
  416. ;----------------------------------------------------------------------
  417. ;  UNATTENDED - Process incoming data and check for changes in video 
  418. ;  data, format and send to manned system.    Maintains 18 or less characters
  419. ;  in output buffer, ensures maximum throughput.
  420. ;----------------------------------------------------------------------
  421. UNATTENDED        PROC    NEAR
  422.         ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  423.                 MOV     BP,SP                    ;Save stack pointer for exit
  424.                 CALL    INPUT_PROCESSING        ;Process any buffered data
  425.                 MOV     AX,OUT_BUFF_HEAD        ;Get the head pointer
  426.                 MOV     BX,OUT_BUFF_TAIL        ;Get the tail pointer
  427.                 MOV     CX,18D                    ;Check for bytes in buffer
  428. UA_10:
  429.                 CMP     AX,BX                    ;Less than 18 bytes in buffer
  430.                 JZ        UA_30                    ;Yes, then compare video
  431.                 INC     AX                        ;Increment head pointer
  432.                 CMP     OUT_BUFF_END,AX         ;Beyond end of buffer area?
  433.                 JNE     UA_20                    ;No, then don't reset
  434.                 MOV     AX,OUT_BUFF_BEGIN        ;Yes, reset to buffer begin
  435. UA_20:
  436.                 LOOP    UA_10                    ;Check all 18 bytes
  437.                 JMP     UA_EXIT                 ;More than 18, exit
  438. UA_30:
  439.                 MOV     VID_RAM_OFFSET,0        ;Start at address 0
  440.                 MOV     BYTE PTR BLOCK_COUNT,0    ;Reset block counter
  441. ;
  442. ;        compare the video copy with the video ram
  443. ;
  444. UA_40:
  445.                 PUSH    DS                        ;Save data segment
  446.                 MOV     SI,VID_RAM_OFFSET        ;Get the current offset
  447.                 MOV     DI,TEMP_VIDEO_PTR        ;Dest. ES:DI temp video buffer
  448.                 MOV     AX,VIDEO_SEGMENT        ;Get video Segment register
  449.                 MOV     DS,AX                    ;Source DS:SI video RAM
  450. ;
  451. ;        transfer block_size words of data from video RAM to the temp buffer
  452. ;
  453.                 MOV     CX,BLOCK_SIZE            ;Get count of words to transfer
  454.                 CLD
  455.                 CMP     BYTE PTR CS:DESNOW_FLAG,0 ;Check desnow flag
  456.                 JZ        UA_70
  457.                 SAL     CX,1                    ;Convert words to bytes
  458.                 MOV     DX,3DAH                 ;CGA status port
  459. UA_50:
  460.                 IN        AL,DX                    ;Get status byte
  461.                 TEST    AL,1                    ;Test display enable
  462.                 JNZ     UA_50                    ;If in Hor. sync then wait
  463.                 CLI                             ;Disable interrupts
  464. UA_60:
  465.                 IN        AL,DX                    ;Get status byte
  466.                 TEST    AL,1                    ;Test display enable
  467.                 JZ        UA_60                    ;Wait for Hor. sync
  468.                 MOVSB                            ;Transfer one byte
  469.                 STI                             ;Enable interrupts
  470.                 LOOP    UA_50                    ;Transfer block size words
  471.                 JMP     UA_80
  472. UA_70:
  473.                 REP     MOVSW
  474. UA_80:
  475.                 POP     DS                        ;Restore data segment
  476. ;
  477. ;        compare the block from video RAM with the video copy
  478. ;
  479.                 MOV     CX,BLOCK_SIZEX2         ;Number of words to compare
  480.                 MOV     SI,TEMP_VIDEO_PTR        ;Point to block of video data
  481.                 MOV     DI,VIDEO_COPY            ;Point to video copy
  482.                 ADD     DI,VID_RAM_OFFSET        ;Adjust for current block
  483.                 REPE    CMPSB                    ;Compare while equal
  484.                 JNE     UA_90                    ;No match, format & send block
  485.                 MOV     AX,VID_RAM_OFFSET        ;Get current block pointer
  486.                 ADD     AX,BLOCK_SIZEX2         ;Point to next block
  487.                 MOV     VID_RAM_OFFSET,AX        ;And save the pointer
  488.                 INC     BYTE PTR BLOCK_COUNT    ;Increment current block count
  489.                 CMP     AX,4000D                ;Check for end of video RAM
  490.                 JNZ     UA_40                    ;No, keep checking the RAM
  491.                 MOV     VID_RAM_OFFSET,0        ;Yes, reset to begin of video
  492.                 JMP     UA_100                    ;Check for change in cursor
  493. ;
  494. ;        data doesn't match, format and send to manned system
  495. ;
  496. UA_90:
  497.                 INC     CX                        ;Adjust count
  498.                 AND     CX,1                    ;LSB indicates char or attr.
  499.                 CALL    TRANSFER_BLOCK            ;Prepare to send block of data
  500. ;
  501. ;        Check for a change in the cursor position
  502. ;
  503. UA_100:
  504.                 MOV     AX,40H                    ;Set ES to BIOS data segment
  505.                 MOV     ES,AX
  506.                 MOV     BX,ES:[50H]             ;Get current cursor position
  507.                 CMP     BX,CURSOR_POSITION        ;Compare with copy
  508.                 JZ        UA_EXIT                 ;No change, skip
  509.                 MOV     CURSOR_POSITION,BX        ;Save new cursor position
  510.                 MOV     AL,0D2H                 ;Sync bits, set position
  511.                 MOV     AH,1                    ;Use output buffer
  512.                 CALL    PUT_BUFF_DATA            ;Send sync byte
  513.                 MOV     AL,BL                    ;Low byte
  514.                 CALL    PUT_BUFF_DATA
  515.                 MOV     AL,BH                    ;High byte
  516.                 CALL    PUT_BUFF_DATA
  517. UA_EXIT:
  518.                 RET
  519. UNATTENDED        ENDP
  520.  
  521. ;----------------------------------------------------------------------
  522. ;  Get data from the unattended input buffer and process
  523. ;  Input - Nothing
  524. ;  Output - Keyboard buffer or shift status is updated
  525. ;  Changes - Nothing
  526. ;----------------------------------------------------------------------
  527. INPUT_PROCESSING PROC     NEAR
  528.                 PUSH    AX                        ;Save register
  529.                 PUSH    DX
  530.                 PUSH    ES
  531.                 MOV     AX,40H                    ;Set ES to BIOS data area
  532.                 MOV     ES,AX
  533. IP_10:
  534.                 CMP     BYTE PTR CONNECT_FLAG,0 ;Are we connected
  535.                 JZ        IP_20                    ;No, don't check carrier
  536.                 CALL    CHECK_CARRIER            ;Yes check for carrier loss
  537.                 JZ        IP_50                    ;Carrier loss, reset and exit
  538. IP_20:
  539.                 MOV     AH,0                    ;Use input buffer
  540.                 CALL    GET_BUFF_DATA            ;Get a byte of data
  541.                 JC        IP_30                    ;If data then process
  542.                 JMP     IP_EXIT                 ;Otherwise exit
  543. ;
  544. ;        Check to see if expecting ASCII data
  545. ;
  546. IP_30:
  547.                 CMP     ASCII_FLAG,0            ;Check ASCII flag
  548.                 JZ        IP_70                    ;0=not expecting data here
  549.                 CMP     ASCII_FLAG,1            ;Check for received 1st byte
  550.                 JNZ     IP_40                    ;Jump if second byte
  551.                 MOV     KEY_ONE,AL                ;Save scan code, byte one
  552.                 INC     BYTE PTR ASCII_FLAG     ;Indicate receiving one byte
  553.                 JMP     IP_10                    ;Process next byte
  554. IP_40:
  555.                 MOV     KEY_TWO,AL                ;Save ASCII code, byte two
  556.                 MOV     AL,KEY_ONE                ;Get ASCII code
  557.                 MOV     AH,KEY_TWO                ;Get scan code
  558.                 CMP     AX,WORD PTR EXIT_CODE    ;Check for exit code
  559.                 JNZ     IP_60                    ;No,then continue processing
  560. IP_50:                                            ;Otherwise reset connect & exit
  561.                 CALL    CLEAR_INBUFF            ;Clear input buffer
  562.                 CALL    CLEAR_OUTBUFF            ;Clear output buffer
  563.                 MOV     BYTE PTR COMM_INT_STA,0 ;Reset transmitting data flag
  564.                 CALL    IU_10                    ;reinit and reset modem
  565.                 CLI                             ;Disable interrupts
  566.                 MOV     BYTE PTR CONNECT_FLAG,0 ;Reset the connect flag
  567.                 MOV     BYTE PTR ASCII_FLAG,0    ;Reset ASCII flag
  568.                 MOV     BYTE PTR SHIFT_FLAG,0    ;Reset shift flag
  569.                 MOV     BYTE PTR ES:[17H],0     ;Reset any shift status
  570.                 MOV     SP,BP                    ;Clean the stack
  571.                 RET                             ;And exit unattended routine
  572. IP_60:
  573.                 CALL    PUT_KEY_DATA            ;And stuff in keyboard buffer
  574.                 MOV     BYTE PTR ASCII_FLAG,0    ;Reset ASCII flag for next data
  575.                 JMP     IP_10                    ;Process next byte
  576. ;
  577. ;        Check to see if expecting shift data
  578. ;
  579. IP_70:
  580.                 CMP     BYTE PTR SHIFT_FLAG,0    ;Check shift flag
  581.                 JZ        IP_80                    ;0=not expecting data here
  582.                 MOV     ES:[17H],AL             ;And save in shift status
  583.                 MOV     BYTE PTR SHIFT_FLAG,0    ;Reset shift flag for next data
  584.                 JMP     IP_10                    ;Process next byte
  585. ;
  586. ;        Check to see if it's a sync byte
  587. ;
  588. IP_80:
  589.                 CMP     AL,0FEH                 ;Check for ASCII sync byte
  590.                 JNZ     IP_90                    ;If not then check for shift
  591.                 INC     BYTE PTR ASCII_FLAG     ;Indicate received FEh
  592.                 JMP     IP_10                    ;Process next byte
  593. IP_90:
  594.                 CMP     AL,0FDH                 ;Check for shift sync byte
  595.                 JNZ     IP_100                    ;If not then throw away
  596.                 INC     BYTE PTR SHIFT_FLAG     ;Indicate received FDh
  597. IP_100:
  598.                 JMP     IP_10                    ;Process till buffer empty
  599. IP_EXIT:
  600.                 POP     ES                        ;Restore registers
  601.                 POP     DX
  602.                 POP     AX
  603.                 RET
  604. INPUT_PROCESSING ENDP
  605.  
  606. ;----------------------------------------------------------------------
  607. ;  Formats the data in temporary video buffer and puts it into the
  608. ;  output buffer
  609. ;  Input - CX=0 Transfer character data to output buffer
  610. ;           CX=1 Transfer attribute data to output buffer
  611. ;  Output - Nothing
  612. ;  Changes - AX, BX, CX, SI, DI
  613. ;----------------------------------------------------------------------
  614. TRANSFER_BLOCK    PROC    NEAR
  615.                 OR        CX,CX                    ;Set flags
  616.                 JZ        TB_10                    ;Jump if character data
  617.                 MOV     AL,0FFH                 ;Sync byte for attr. data
  618.                 JMP     TB_20
  619. TB_10:
  620.                 MOV     AL,0FEH                 ;Sync byte for char. data
  621. TB_20:
  622.                 MOV     AH,1                    ;Use output buffer
  623.                 CALL    PUT_BUFF_DATA            ;Put sync byte in output buff.
  624.                 MOV     AL,BLOCK_COUNT
  625.                 MOV     AH,1                    ;Use output buffer
  626.                 CALL    PUT_BUFF_DATA            ;Send the block number
  627.                 MOV     SI,TEMP_VIDEO_PTR        ;Point to block of video data
  628.                 ADD     SI,CX                    ;Adjust for char. or attr.
  629.                 MOV     DI,VIDEO_COPY            ;Point to video copy
  630.                 ADD     DI,VID_RAM_OFFSET        ;Adjust for block offset
  631.                 ADD     DI,CX                    ; and character or attribute
  632.                 MOV     CX,BLOCK_SIZE            ;Number of bytes to send
  633.                 CLD                             ;Forward direction
  634. TB_30:
  635.                 LODSW                            ;Get the unmatched data
  636.                 MOV     AH,1                    ;Use the output buffer
  637.                 CALL    PUT_BUFF_DATA            ;Put the video data in out buff
  638.                 STOSB                            ;Save video data in copy
  639.                 INC     DI                        ;Adjust for word offset
  640.                 LOOP    TB_30                    ;Send block size bytes of data
  641.                 RET
  642. TRANSFER_BLOCK    ENDP
  643.  
  644. ;----------------------------------------------------------------------
  645. ;  Put a byte of data into the unattended keyboard buffer.
  646. ;  Input - AL contains ASCII to be put into buffer.
  647. ;           AH contains scan code to be put into buffer.
  648. ;  Output - Carry Set - Byte placed in buffer successfully
  649. ;            Carry Reset - Buffer full, byte not stored in buffer
  650. ;  Changes - Nothing
  651. ;----------------------------------------------------------------------
  652. PUT_KEY_DATA    PROC    NEAR
  653.                 PUSH    BX                        ;Save registers
  654.                 PUSH    SI
  655.                 PUSH    DI
  656.                 MOV     SI,1AH                    ;Point to keyboard head pointer
  657.                 CLI                             ;Don't allow interrupts
  658.                 MOV     BX,ES:[1CH]             ;Get the buffer tail pointer
  659.                 MOV     DI,BX                    ;Save the tail pointer
  660.                 INC     BX                        ;Point to next data storage
  661.                 INC     BX
  662.                 CMP     BX,3EH                    ;Beyond end of buffer area?
  663.                 JNE     PK_10                    ;No, then don't reset
  664.                 MOV     BX,1EH                    ;Yes, reset to buffer begin
  665. PK_10:
  666.                 CMP     BX,ES:[1AH]             ;Test for buffer full
  667.                 JE        PK_EXIT                 ;If the same, don't save it
  668.                                                 ; exit, carry is already reset
  669.                 MOV     ES:[DI],AX                ;Store the data in buffer
  670.                 MOV     ES:[1CH],BX             ;Save new tail pointer
  671.                 STC                             ;Indicate data stored OK
  672. PK_EXIT:
  673.                 POP     DI
  674.                 POP     SI
  675.                 POP     BX
  676.                 STI                             ;Enable interrupts
  677.                 RET
  678. PUT_KEY_DATA     ENDP
  679.  
  680. ;======================================================================
  681. ;  COMMON ROUTINES - These routines are common to both the unattended
  682. ;  processing portion of the program and the manned processing portion.
  683. ;======================================================================
  684.  
  685. ;----------------------------------------------------------------------
  686. ;  Get a byte of data from a buffer.  Byte pointed to by head pointer is
  687. ;  is next data byte.  If head=tail, no data in buffer.
  688. ;  Input - AH - Buffer to use 0=Input buffer, 1=Output buffer.
  689. ;  Output - Carry Set - Byte from buffer is in AL
  690. ;            Carry Reset - No data in buffer
  691. ;  Changes - AL
  692. ;----------------------------------------------------------------------
  693. GET_BUFF_DATA    PROC    NEAR
  694.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  695.                 PUSH    BX                        ;Save registers
  696.                 PUSH    SI
  697.                 CMP     AH,0                    ;Check which buffer to use
  698.                 JNZ     GD_10                    ;Jump for output buffer
  699.                 MOV     SI,OFFSET IN_BUFF_HEAD    ;Point to input buffer
  700.                 JMP     GD_20                    ;Skip over out buffer
  701. GD_10:
  702.                 MOV     SI,OFFSET OUT_BUFF_HEAD ;Point to output buffer
  703. GD_20:
  704.                 CLI                             ;Don't allow interrupts
  705.                 MOV     BX,[SI]                 ;Get the buffer head pointer
  706.                 CMP     BX,2[SI]                ;Test for data in buffer
  707.                 JE        GD_EXIT                 ;If the same, no data so
  708.                                                 ; exit, carry is already reset
  709.                 MOV     AL,[BX]                 ;Get the data
  710.                 INC     BX                        ;Point to data in buffer
  711.                 CMP     6[SI],BX                ;Beyond end of buffer area?
  712.                 JNE     GD_30                    ;No, then don't reset
  713.                 MOV     BX,4[SI]                ;Yes, reset to buffer begin
  714. GD_30:
  715.                 MOV     [SI],BX                 ;Save new head pointer
  716.                 STC                             ;Indicate data is in AL
  717. GD_EXIT:
  718.                 POP     SI                        ;Restore registers
  719.                 POP     BX
  720.                 STI                             ;Enable interrupts
  721.                 RET
  722. GET_BUFF_DATA    ENDP
  723.  
  724. ;----------------------------------------------------------------------
  725. ;  Put a byte of data into a buffer.  Byte is stored at location
  726. ;  pointed to by tail pointer.
  727. ;  Input - AL contains data to be put into buffer.
  728. ;           AH - Buffer to use 0=Input buffer, 1=Output buffer
  729. ;  Output - Carry Set - byte placed in buffer successfully
  730. ;            Carry Reset - Buffer full, byte not stored in buffer
  731. ;  Changes - Nothing
  732. ;----------------------------------------------------------------------
  733. PUT_BUFF_DATA    PROC    NEAR
  734.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  735.                 PUSH    AX                        ;Save registers
  736.                 PUSH    BX
  737.                 PUSH    DX
  738.                 PUSH    SI
  739.                 PUSH    DI
  740.                 PUSH    DS
  741.                 PUSH    CS                        ;Set data segment to CS
  742.                 POP     DS
  743.                 CMP     AH,0                    ;Check which buffer to use
  744.                 JNZ     PD_10                    ;Jump for output buffer
  745.                 MOV     SI,OFFSET IN_BUFF_HEAD    ;Point to input buffer
  746.                 JMP     PD_20                    ;Skip over out buffer
  747. PD_10:
  748.                 MOV     SI,OFFSET OUT_BUFF_HEAD ;Point to output buffer
  749. PD_20:
  750.                 CLI                             ;Don't allow interrupts
  751.                 MOV     BX,2[SI]                ;Get the buffer tail pointer
  752.                 MOV     DI,BX                    ;Save the tail pointer
  753.                 INC     BX                        ;Point to next data storage
  754.                 CMP     6[SI],BX                ;Beyond end of buffer area?
  755.                 JNE     PD_30                    ;No, then don't reset
  756.                 MOV     BX,4[SI]                ;Yes, reset to buffer begin
  757. PD_30:
  758.                 CMP     BX,[SI]                 ;Test for buffer full
  759.                 JE        PD_40                    ;If so, exit carry is reset
  760.  
  761.                 MOV     [DI],AL                 ;Store the data in buffer
  762.                 MOV     2[SI],BX                ;Save new tail pointer
  763.                 STC                             ;Indicate data stored ok
  764. PD_40:
  765.                 PUSHF                            ;Save the flags
  766.                 CMP     BYTE PTR COMM_INT_STA,0 ;Transmit int. running?
  767.                 JNZ     PD_50                    ;Yes, so exit
  768.                 MOV     AX,OUT_BUFF_HEAD        ;Is data in output buffer
  769.                 CMP     AX,OUT_BUFF_TAIL
  770.                 JZ        PD_50                    ;No, so exit
  771.                 MOV     BYTE PTR COMM_INT_STA,1 ;Set transmitting data flag
  772.                 MOV     AH,1                    ;Use the output buffer
  773.                 CALL    GET_BUFF_DATA            ;Get data from output buffer
  774.                 MOV     DX,COMM_PORT            ;Get port base address
  775.                 OUT     DX,AL                    ;Send the data out the port
  776. PD_50:
  777.                 STI                             ;Enable interrupts
  778.                 POPF                            ;Restore flags
  779.                 POP     DS                        ;Restore registers
  780.                 POP     DI
  781.                 POP     SI
  782.                 POP     DX
  783.                 POP     BX
  784.                 POP     AX
  785.                 RET
  786. PUT_BUFF_DATA    ENDP
  787.  
  788. ;----------------------------------------------------------------------
  789. ;  Clear the input buffer
  790. ;  Input - Nothing
  791. ;  Output - Nothing
  792. ;  Changes - Nothing
  793. ;----------------------------------------------------------------------
  794. CLEAR_INBUFF    PROC    NEAR
  795.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  796.                 PUSH    AX                        ;Save register
  797.                 CLI                             ;Disable interrupts
  798.                 MOV     AX,IN_BUFF_TAIL         ;Get buffer tail pointer
  799.                 MOV     IN_BUFF_HEAD,AX         ;Make head equal tail
  800.                 STI                             ;Enable interrupts
  801.                 POP     AX
  802.                 RET
  803. CLEAR_INBUFF    ENDP
  804.  
  805. ;----------------------------------------------------------------------
  806. ;  Clear the output buffer
  807. ;  Input - Nothing
  808. ;  Output - Nothing
  809. ;  Changes - Nothing
  810. ;----------------------------------------------------------------------
  811. CLEAR_OUTBUFF    PROC    NEAR
  812.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  813.                 PUSH    AX                        ;Save register
  814.                 CLI                             ;Disable interrupts
  815.                 MOV     AX,OUT_BUFF_TAIL        ;Get buffer tail pointer
  816.                 MOV     OUT_BUFF_HEAD,AX        ;Make head equal tail
  817.                 STI                             ;Enable interrupts
  818.                 POP     AX
  819.                 RET
  820. CLEAR_OUTBUFF    ENDP
  821.  
  822. ;----------------------------------------------------------------------
  823. ;  Reset the modem and send the setup string to initialize
  824. ;  Input - AL - 0 use setup string 1, 1 use setup string 2
  825. ;  Output - Nothing
  826. ;  Changes - Nothing
  827. ;----------------------------------------------------------------------
  828. RESET_MODEM     PROC    NEAR
  829.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  830.                 PUSH    SI                        ;Save registers
  831.                 PUSH    DX
  832.                 PUSH    AX
  833.                 CMP     BYTE PTR CONNECT_FLAG,0 ;Is modem connected?
  834.                 JZ        RM_20                    ;No then send setup only
  835.                 CALL    CLEAR_OUTBUFF            ;Empty the output buffer
  836.                 MOV     BYTE PTR CONNECT_FLAG,0 ;Reset connect flag
  837.                 MOV     AL,1                    ;Wait a second for guard time
  838.                 CALL    DELAY
  839.                 MOV     SI,OFFSET MODEM_ESCAPE    ;Send modem escape code
  840.                 CALL    LOAD_ZSTRING
  841.                 MOV     AL,2                    ;Wait
  842.                 CALL    DELAY
  843.                 MOV     SI,OFFSET MODEM_HANGUP    ;Send modem hangup code
  844.                 CALL    LOAD_ZSTRING
  845.                 MOV     AL,1                    ;Wait for a second
  846.                 CALL    DELAY
  847. RM_20:
  848.                 MOV     AL,SPEED_FLAG            ;Get speed flag
  849.                 CALL    SET_BAUD_RATE
  850.                 MOV     SI,OFFSET MODEM_ATTENTION ;Point to modem attention
  851.                 CALL    LOAD_ZSTRING              ;Put it into output buffer
  852.                 MOV     AL,1                    ;Wait for a second
  853.                 CALL    DELAY
  854.                 POP     AX                        ;Get setup string to use
  855.                 CMP     AL,0                    ;Test for string 1
  856.                 JNZ     RM_30                    ;No, then use string 2
  857.                 MOV     SI,OFFSET MODEM_SETUP1    ;Point to modem setup string 1
  858.                 JMP     RM_40
  859. RM_30:
  860.                 MOV     SI,OFFSET MODEM_SETUP2    ;Point to modem setup string 2
  861. RM_40:
  862.                 CALL    LOAD_ZSTRING            ;Load setup string to modem
  863.                 MOV     AL,1                    ;Wait a second
  864.                 CALL    DELAY
  865.                 MOV     SI,OFFSET MODEM_SETUP3    ;Point to modem setup string 3
  866.                 CALL    LOAD_ZSTRING            ;Load setup string to modem
  867.                 CALL    CLEAR_INBUFF            ;Clear the input buffer
  868.                 POP     DX                        ;Restore registers
  869.                 POP     SI
  870.                 RET
  871. RESET_MODEM     ENDP
  872.  
  873. ;----------------------------------------------------------------------
  874. ;  Check carrier reads the carrier status signal and sets Z flag to 
  875. ;  indicate status
  876. ;  Input - Nothing
  877. ;  Output - Zero flag 0 - Carrier
  878. ;            Zero flag 1 - No Carrier detected
  879. ;  Changes - Nothing
  880. ;----------------------------------------------------------------------
  881. CHECK_CARRIER    PROC    NEAR
  882.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  883.                 PUSH    AX                        ;Save registers
  884.                 PUSH    DX
  885.                 MOV     DX,COMM_PORT            ;Get the comm base address
  886.                 ADD     DX,6                    ;Modem status register
  887.                 IN        AL,DX                    ;Get the current status
  888.                 TEST    AL,10000000B            ;Data carrier detect
  889.                 POP     DX                        ;Restore registers
  890.                 POP     AX
  891.                 RET
  892. CHECK_CARRIER    ENDP
  893.  
  894. ;----------------------------------------------------------------------
  895. ;  DELAY - delay approximate number of seconds in AL
  896. ;  Input - AL
  897. ;  Output - Nothing (just waits till AL is zero)
  898. ;  Changes - Nothing
  899. ;----------------------------------------------------------------------
  900. DELAY            PROC    NEAR
  901.                 PUSH    CX                        ;Save registers
  902.                 PUSH    DX
  903.                 PUSH    DI
  904.                 PUSH    AX
  905.                 XOR     AH,AH                    ;Read system time
  906.                 INT     1AH
  907.                 MOV     DI,DX                    ;Save low tick count
  908.                 MOV     SI,CX                    ;Save high tick count
  909.                 POP     AX                        ;Get number of seconds to delay
  910.                 PUSH    AX
  911.                 XOR     CX,CX                    ;Zero CX
  912.                 MOV     CL,AL                    ;Put seconds into loop counter
  913. D_10:
  914.                 ADD     DI,19D                    ;Approximate counts in a second
  915.                 ADC     SI,0                    ;Add carry to SI
  916.                 LOOP    D_10
  917. D_20:
  918.                 XOR     AH,AH                    ;Read system time
  919.                 INT     1AH
  920.                 CMP     SI,CX
  921.                 JNE     D_20
  922.                 CMP     DI,DX                    ;End of delay time
  923.                 JGE     D_20                    ;No, keep checking
  924.                 POP     AX                        ;Restore registers
  925.                 POP     DI
  926.                 POP     DX
  927.                 POP     CX
  928.                 RET
  929. DELAY            ENDP
  930.  
  931. ;----------------------------------------------------------------------
  932. ;  String at SI is placed in output buffer to be sent out serial port
  933. ;  Input - SI points to zero terminated string
  934. ;  Output - Nothing
  935. ;  Changes - SI
  936. ;----------------------------------------------------------------------
  937. LOAD_ZSTRING    PROC    NEAR
  938.                 PUSH    AX                        ;Save register
  939.                 MOV     AH,1                    ;Use output buffer
  940.                 CLD                             ;Forward
  941. LZ_10:
  942.                 LODSB                            ;Get a byte of data
  943.                 CMP     AL,0                    ;Check for zero
  944.                 JZ        LZ_EXIT                 ;Yes, then exit
  945.                 CALL    PUT_BUFF_DATA            ;No, put in output buffer
  946.                 JMP     LZ_10                    ;Process next data
  947. LZ_EXIT:
  948.                 POP     AX                        ;Restore register
  949.                 RET
  950. LOAD_ZSTRING    ENDP
  951.  
  952. ;----------------------------------------------------------------------
  953. ;  Check for a key in the keyboard buffer, if one is there, get it
  954. ;  Input - Nothing
  955. ;  Output - Zero flag = 1 no key in buffer
  956. ;            Zero flag = 0 key is in AX
  957. ;  Changes - AX
  958. ;----------------------------------------------------------------------
  959. GET_KEYSTROKE    PROC    NEAR
  960.         ASSUME    CS:CSEG,DS:NOTHING,ES:NOTHING,SS:NOTHING
  961.                 MOV     AH,1                    ;Check for keystroke
  962.                 INT     16H                     ;Keyboard BIOS
  963.                 JZ        GK_EXIT                 ;No key so exit
  964.                 PUSHF                            ;Save the zero flag
  965.                 XOR     AH,AH                    ;Get the keystroke
  966.                 INT     16H
  967.                 POPF                            ;Restore the zero flag
  968. GK_EXIT:
  969.                 RET
  970. GET_KEYSTROKE    ENDP
  971.  
  972. ;----------------------------------------------------------------------
  973. ;  Change the interrupt 8 vector to the interrupt service routine of
  974. ;  PCREMOTE
  975. ;  Input - CX points to starting buffer location
  976. ;  Output - Input and output buffer points are initialized
  977. ;  Changes - BX, CX
  978. ;----------------------------------------------------------------------
  979. INIT_BUFFERS    PROC    NEAR
  980.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  981.                 MOV     BX,OFFSET IN_BUFF_HEAD    ;In buffer will be here
  982.                 MOV     WORD PTR [BX],CX        ; Set head pointer to buffer
  983.                 MOV     WORD PTR 2[BX],CX        ;Set tail pointer to buffer
  984.                 MOV     WORD PTR 4[BX],CX        ;Set begin of buffer
  985.                 ADD     CX,IN_BUFF_SIZE         ;CX Points to end of in buffer
  986.                 MOV     WORD PTR 6[BX],CX        ;Set end of buffer
  987.                 MOV     BX,OFFSET OUT_BUFF_HEAD ;Out buffer after in buffer
  988.                 MOV     WORD PTR [BX],CX        ; Set head pointer to buffer
  989.                 MOV     WORD PTR 2[BX],CX        ;Set tail pointer to buffer
  990.                 MOV     WORD PTR 4[BX],CX        ;Set begin of buffer
  991.                 ADD     CX,OUT_BUFF_SIZE        ;CX Points to end of out buffer
  992.                 MOV     WORD PTR 6[BX],CX        ;Set end of buffer
  993.                 RET
  994. INIT_BUFFERS    ENDP
  995.  
  996. ;----------------------------------------------------------------------
  997. ;  Change the interrupt 8 vector to the interrupt service routine of
  998. ;  PCREMOTE
  999. ;  Input - Nothing
  1000. ;  Output - Interrupt vector 8 points to INT8
  1001. ;  Changes - AX, DX, BX, ES
  1002. ;----------------------------------------------------------------------
  1003. MODIFY_INT8     PROC    NEAR
  1004.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1005. ;
  1006. ;        Change interrupt 8 vector
  1007. ;
  1008.                 MOV     AX,3508H                ;Get interrupt 8h vector
  1009.                 INT     21H
  1010.                 MOV     OLDINT_8,BX             ;And save it
  1011.                 MOV     OLDINT_8[2],ES
  1012.                 MOV     AX,2508H                ;Set interrupt 8h vector
  1013.                 MOV     DX,OFFSET INT8            ; to point to new routine
  1014.                 INT     21H
  1015.                 RET
  1016. MODIFY_INT8     ENDP
  1017.  
  1018. ;----------------------------------------------------------------------
  1019. ;  Set baud rate to 1200 or 2400
  1020. ;  Input - AL -0 1200 baud, 1 2400 baud
  1021. ;  Output - Nothing
  1022. ;  Changes - Nothing
  1023. ;----------------------------------------------------------------------
  1024. SET_BAUD_RATE    PROC    NEAR
  1025.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1026.                 PUSH    DX                        ;Save registers
  1027.                 PUSH    BX
  1028.                 PUSH    SI
  1029.                 PUSH    AX
  1030.                 MOV     DX,COMM_PORT            ;Get port address
  1031.                 ADD     DX,3                    ;Line control register
  1032.                 MOV     AL,83H                    ;Toggle port address to
  1033.                 OUT     DX,AL                    ; prepare to set baud rate
  1034.                 SUB     DX,2                    ;Baud rate divisor MSB port
  1035.                 POP     AX                        ;Restore baud rate
  1036.                 PUSH    AX
  1037.                 XOR     AH,AH                    ;Zero AH
  1038.                 MOV     SI,AX                    ;Save in index register
  1039.                 SHL     SI,1                    ;Multiply by 2, word address
  1040.                 MOV     BX,OFFSET BAUD_RATE     ;Point to baud rates
  1041.                 MOV     AL,[BX+SI]                ;Get baud rate MSB
  1042.                 OUT     DX,AL                    ; and set it
  1043.                 DEC     DX                        ;Baud rate divisor LSB port
  1044.                 MOV     AL,1[BX+SI]             ;Get baud rate LSB
  1045.                 OUT     DX,AL                    ; and set it
  1046.                 ADD     DX,3                    ;Line control register
  1047.                 MOV     AL,3                    ;8 data bits,1 stop,no parity
  1048.                 OUT     DX,AL                    ;Set data bit pattern
  1049.                                                 ; and toggle port address
  1050.                 POP     AX                        ;Restore registers
  1051.                 POP     SI
  1052.                 POP     BX
  1053.                 POP     DX
  1054.                 RET
  1055. SET_BAUD_RATE    ENDP
  1056.  
  1057. ;======================================================================
  1058. ;  Initialize routines.  The initialize routine for unattended is first
  1059. ;  because it must remain resident.
  1060. ;======================================================================
  1061.  
  1062. ;-----------------------------------------------------------------------------
  1063. ;  Initialize the unattended program.
  1064. ;-----------------------------------------------------------------------------
  1065. INIT_UNATTENDED PROC    NEAR
  1066.         ASSUME    CS:CSEG,DS:CSEG,ES:CSEG,SS:NOTHING
  1067.                 CALL    IU_10                    ;Init pointers,clear video copy
  1068.                 CALL    MODIFY_INT8             ;Change INT 8 vector
  1069. ;
  1070. ;        Terminate-Stay-Resident
  1071. ;
  1072.                 MOV     DX,VIDEO_COPY            ;Start of video copy
  1073.                 ADD     DX,4000D                ;Allow room for video copy
  1074.                 INT     27H                     ;Terminate-Stay-Resident
  1075. ;
  1076. ;        Initialize buffer pointers and video copy pointer
  1077. ;
  1078. IU_10:
  1079.                 PUSH    ES                        ;Save extra segment
  1080.                 MOV     CX,OFFSET INITIALIZE    ;CX points to begin of buffer
  1081.                 ADD     CX,256D                 ;Leave room for TSR stack
  1082.                 CALL    INIT_BUFFERS            ;Initalize the buffer pointers
  1083.                 INC     CX                        ;Point to copy of video ram
  1084.                 MOV     TEMP_VIDEO_PTR,CX        ;Save address of temp video buf
  1085.                 ADD     CX,BLOCK_SIZEX2         ;Save room for temp video data
  1086.                 MOV     VIDEO_COPY,CX            ;Save address of video copy
  1087. ;
  1088. ;        fill video RAM image with with space code since screen
  1089. ;        of manned system is blanked when connected
  1090. ;
  1091.                 PUSH    CS                        ;Video copy is destination
  1092.                 POP     ES                        ;ES:DI points to video copy
  1093.                 MOV     DI,WORD PTR VIDEO_COPY
  1094.                 MOV     AX,0720H                ;Data to fill buffer
  1095.                 CLD                             ;Move upward
  1096.                 MOV     CX,2000D                ;Move 2000 words
  1097.                 REP     STOSW                    ;Fill to force screen dump
  1098.                 MOV     CURSOR_POSITION,0FFFFH    ;Force cursor position update
  1099.                 MOV     AL,1                    ;Use setup string 2
  1100.                 CALL    RESET_MODEM             ;Reset the modem
  1101.                 POP     ES                        ;Restore extra segment
  1102.                 RET
  1103. INIT_UNATTENDED ENDP
  1104.  
  1105. ;-----------------------------------------------------------------------------
  1106. ;  INITIALIZE - Initialize the program.  Determine whether it is manned
  1107. ;  or unattended by processing the command line.  Initialize the serial
  1108. ;  port.
  1109. ;-----------------------------------------------------------------------------
  1110. INITIALIZE        PROC    NEAR
  1111.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1112. ;
  1113. ;        Display copyright notice.
  1114. ;
  1115.                 MOV     DX,OFFSET COPYRIGHT     ;Display copyright notice
  1116.                 MOV     AH,9                    ;Display string
  1117.                 INT     21H
  1118. ;
  1119. ;        check to see if the program is already in memory
  1120. ;
  1121.                 MOV     BYTE PTR START,0        ;Zero word to avoid false match
  1122.                 XOR     BX,BX                    ;Initialize search segment
  1123.                 MOV     AX,CS                    ;Save current segment in AX
  1124.                 CLD                             ;Clear direction flag
  1125. I_10:
  1126.                 INC     BX                        ;Increment search segment
  1127.                 CMP     AX,BX                    ;Reached current segment?
  1128.                 JE        I_20                    ;Yes, PCREMOTE not resident
  1129.                 MOV     ES,BX                    ;Point ES to search segment
  1130.                 MOV     SI,OFFSET START         ;Start of compare area
  1131.                 MOV     DI,SI                    ;Make offsets equal
  1132.                 MOV     CX,16D                    ;Check 16 characters
  1133.                 REPE    CMPSB                    ;Compare the strings
  1134.                 JNE     I_10                    ;Compare failed
  1135.                 MOV     AH,09H                    ;Print string
  1136.                 MOV     DX,OFFSET PROG_RES        ;Display program resident mess.
  1137.                 INT     21H
  1138.                 INT     20H                     ;Terminate
  1139. ;
  1140. ;        Process command line for switches.
  1141. ;
  1142. I_20:
  1143.                 PUSH    CS                        ;Restore ES
  1144.                 POP     ES
  1145.                 MOV     BX,80H                    ;Point to command line length
  1146.                 MOV     AH,[BX]                 ;Get command line length
  1147. I_30:
  1148.                 OR        AH,AH                    ;Check for commands
  1149.                 JZ        I_70                    ;None, so don't look
  1150.                 INC     BX                        ;Point to next data
  1151.                 MOV     AL,[BX]                 ;Get data
  1152.                 DEC     AH                        ;Decrement counter
  1153.                 CMP     AL,"/"                    ;Check for slash
  1154.                 JNE     I_30                    ;No, jump to check next data
  1155.                 OR        AH,AH                    ;Check for data after slash
  1156.                 JZ        I_70                    ;No, so don't process
  1157.                 INC     BX                        ;Point to next data
  1158.                 MOV     AL,[BX]                 ;Get data
  1159.                 DEC     AH                        ;Decrement counter
  1160.                 CMP     AL,"2"                    ;Check for COM2
  1161.                 JNE     I_40                    ;No, check for another switch
  1162.                 INC     BYTE PTR COMM_FLAG        ;Set COM2 flag
  1163.                 JMP     I_30                    ;Process next switch
  1164. I_40:
  1165.                 OR        AL,20H                    ;Force data to lower case
  1166.                 CMP     AL,"m"                    ;Check for manned switch
  1167.                 JNE     I_50                    ;No, check for another switch
  1168.                 INC     BYTE PTR MANNED_FLAG    ;Set manned flag
  1169.                 JMP     I_30                    ;Process next switch
  1170. I_50:
  1171.                 CMP     AL,"f"                    ;Check for fast speed
  1172.                 JNE     I_60                    ;No, check for another switch
  1173.                 INC     BYTE PTR SPEED_FLAG     ;Set high speed flag
  1174.                 JMP     I_30                    ;Process next switch
  1175. I_60:
  1176.                 CMP     AL,"d"                    ;Check for desnow
  1177.                 JNE     I_30                    ;No, process next switch
  1178.                 INC     BYTE PTR DESNOW_FLAG    ;Set desnow flag
  1179.                 JMP     I_30                    ;Process next switch
  1180.  
  1181. ;----------------------------------------------------------------------
  1182. ;  Initialize the serial port
  1183. ;----------------------------------------------------------------------
  1184.  
  1185. I_70:
  1186. ;
  1187. ;        get the comm port base address using 2* comm port flag as offset
  1188. ;
  1189.                 PUSH    DS                        ;Save data segment
  1190.                 XOR     BX,BX                    ;Zero BX
  1191.                 MOV     BL,COMM_FLAG            ;Get comm port flag
  1192.                 MOV     SI,BX                    ;Save in index register
  1193.                 SHL     SI,1                    ;Multiply by 2, word address
  1194.                 MOV     AX,40H                    ;Point DS to BIOS data area
  1195.                 MOV     DS,AX
  1196.                 XOR     BX,BX                    ;Point to comm port address
  1197.                 MOV     AX,[BX+SI]                ;Get comm port address
  1198.                 POP     DS                        ;Restore data segment
  1199.                 MOV     COMM_PORT,AX            ;Save comm port address
  1200. ;
  1201. ;        disable the interrupts on the 8250 and initialize DTR and RTS
  1202. ;
  1203.                 CLI                             ;Disable interrupts
  1204.                 MOV     DX,COMM_PORT            ;Get UART base address
  1205.                 ADD     DX,4                    ;Modem control register
  1206.                 MOV     AL,00001011B            ;Set DTR, RTS, and OUT2
  1207.                 OUT     DX,AL
  1208. ;
  1209. ;        set the baud rate of the UART and initialize line control register
  1210. ;
  1211.                 MOV     AL,SPEED_FLAG            ;Get speed flag
  1212.                 CALL    SET_BAUD_RATE
  1213. ;
  1214. ;        modify the interrupt vector for the comm port and set 8259 mask
  1215. ;
  1216.                 CMP     BYTE PTR COMM_FLAG,0    ;Determine INT vector to change
  1217.                 JZ        I_80
  1218.                 MOV     AL,11D                    ;Vector for COM2
  1219.                 MOV     BL,0F7H                 ;Mask for 8259 COM2
  1220.                 JMP     I_90
  1221. I_80:
  1222.                 MOV     AL,12D                    ;Vector for COM1
  1223.                 MOV     BL,0EFH                 ;Mask for 8259 COM1
  1224. I_90:
  1225.                 MOV     AH,25H                    ;Set interrupt for comm vector
  1226.                 MOV     DX,OFFSET INT_COMM        ; to point to routine
  1227.                 INT     21H
  1228.                 IN        AL,21H                    ;Get current 8259 int mask
  1229.                 AND     AL,BL                    ;Mask appropriate int bit
  1230.                 OUT     21H,AL                    ;And set new 8259 mask
  1231. ;
  1232. ;        enable the data received interrupt and reset the 8250
  1233. ;
  1234.                 MOV     DX,COMM_PORT            ;Point to comm port
  1235.                 INC     DX                        ;Point to int enable reg
  1236.                 MOV     AL,3                    ;Enable data received int
  1237.                 OUT     DX,AL
  1238.                 DEC     DX                        ;Point to base address
  1239.                 MOV     CX,7                    ;Reset the serial port
  1240. I_100:
  1241.                 IN        AL,DX                    ;Read registers to reset
  1242.                 INC     DX
  1243.                 LOOP    I_100
  1244. ;
  1245. ;        determine color or monochrome and save appropriate video segment
  1246. ;
  1247.                 MOV     AH,0FH                    ;Determine video mode
  1248.                 INT     10H                     ;By using BIOS int 10
  1249.                 CMP     AL,7                    ;Check for monochrome
  1250.                 JZ        MONOCHROME                      ;Jump if it is
  1251.                 MOV     WORD PTR VIDEO_SEGMENT,0B800H ;Nope, it's CGA or EGA
  1252.                 JMP     I_110                          ;Skip over
  1253. MONOCHROME:
  1254.                 MOV     WORD PTR VIDEO_SEGMENT,0B000H ;It's a monochrome
  1255. I_110:
  1256. ;
  1257. ;        If manned then execute manned initialization, otherwise execute
  1258. ;        unattended initialization.
  1259. ;
  1260.                 CMP     BYTE PTR MANNED_FLAG,0    ;Manned or unattended
  1261.                 JNZ     INIT_MANNED             ;Init the manned routines
  1262.                 JMP     INIT_UNATTENDED         ;Init the unattended routines
  1263. INITIALIZE        ENDP
  1264.  
  1265. ;----------------------------------------------------------------------
  1266. ;  Initialize the manned program.  Initialize buffers, and change INT 8
  1267. ;  vector.
  1268. ;----------------------------------------------------------------------
  1269. INIT_MANNED     PROC    NEAR
  1270.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1271.                 MOV     CX,OFFSET LAST_BYTE     ;CX points to begin of buffer
  1272.                 CALL    INIT_BUFFERS            ;Initalize the buffer pointers
  1273.                 MOV     AX,VIDEO_SEGMENT        ;Set ES to point to video RAM
  1274.                 MOV     ES,AX
  1275.                 JMP     CONNECT_MANNED            ;Run manned portion of program
  1276. INIT_MANNED     ENDP
  1277.  
  1278. ;======================================================================
  1279. ;  Data used by manned portion of program only.  Not required to be
  1280. ;  resident for unattended mode.
  1281. ;======================================================================
  1282. BLOCK_DATA_COUNT DB     0                        ;Number of bytes left to rec.
  1283. TYPE_TRANSFER    DB        0FFH                    ;FF - No data transfer in prog.
  1284.                                                 ;00 - Received FE, char. data
  1285.                                                 ;01 - Received FF, attr. data
  1286. CUR_STATUS        DB        0                        ;0=No cursor data being rec.
  1287.                                                 ; otherwise, byte count
  1288. CUR_LOW         DB        0                        ;Low byte of cursor data
  1289. CUR_HIGH        DB        0                        ;High byte of cursor data
  1290. ENTER_NUMBER    DB        CR,LF,CR,LF,"Enter phone number:$"
  1291. NO_CARRIER        DB        CR,LF,"No carrier.$"
  1292. MODEM_ERROR     DB        CR,LF,"Error.$"
  1293. TERMINATE_MESS    DB        CR,LF,"Returning to DOS.$"
  1294. PROG_RES        DB        CR,LF,"PCREMOTE is already resident.$"
  1295. EXIT_MESSAGE    DB        "╔══════════════════╗"
  1296.                 DB        "║ OK to EXIT? (Y/N)║"
  1297.                 DB        "╚══════════════════╝"
  1298.  
  1299. ;======================================================================
  1300. ;  The manned routine will execute the connect manned routine to call the
  1301. ;  unattended system.  These routines are only used in the manned mode.
  1302. ;======================================================================
  1303.  
  1304. ;----------------------------------------------------------------------
  1305. ;  Connect manned asks for the phone number to call, dials the number
  1306. ;  and waits for connect.  Once connected it sends bursts of 20 CRs at
  1307. ;  one second intervals.  When it receives alpha data it processes video
  1308. ;  data and waits for sync byte (00), then transfers control to the
  1309. ;  manned routine.
  1310. ;----------------------------------------------------------------------
  1311. CONNECT_MANNED    PROC    NEAR
  1312.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1313.                 XOR     AL,AL                    ;Use setup string 1
  1314.                 CALL    RESET_MODEM             ;Reset the modem first
  1315.                 MOV     DX,OFFSET ENTER_NUMBER    ;Point to enter number mess.
  1316.                 MOV     AH,9                    ;Display message
  1317.                 INT     21H
  1318.                 MOV     DX,OFFSET UNATTENDED    ;Unused area as keyboard buffer
  1319.                 MOV     BX,DX                    ;Enter max characters for input
  1320.                 MOV     BYTE PTR [BX],40D
  1321.                 MOV     AH,0AH                    ;Buffered keyboard input
  1322.                 INT     21H                     ;Get the phone number
  1323.                 MOV     AL,1                    ;Wait a second
  1324.                 CALL    DELAY
  1325.                 MOV     SI,OFFSET UNATTENDED    ;Point to phone number
  1326.                 INC     SI                        ;Amount of data in key buffer
  1327.                 XOR     AX,AX                    ;Zero AX
  1328.                 CLD                             ;Forward
  1329.                 LODSB                            ;Get count
  1330.                 OR        AL,AL                    ;Check for no input
  1331.                 JNZ     CM_10                    ;If there is then continue
  1332.                 JMP     EXIT_MANNED             ;No, then exit program
  1333. CM_10:
  1334.                 PUSH    SI                        ;Save pointer
  1335.                 MOV     SI,OFFSET TONE_DIAL     ;Send the tone dial command
  1336.                 CALL    LOAD_ZSTRING
  1337.                 POP     SI                        ;Restore pointer
  1338.                 ADD     SI,AX                    ;Point to end of buffer
  1339.                 INC     SI                        ;Include CR code
  1340.                 MOV     BYTE PTR [SI],0         ;And put a zero on end
  1341.                 DEC     SI                        ;Adjust for previous INC
  1342.                 SUB     SI,AX                    ;Back to begin of buffer
  1343.                 CALL    LOAD_ZSTRING            ;Dial the phone number
  1344.                 MOV     AL,1                    ;Wait a second
  1345.                 CALL    DELAY
  1346.                 CALL    CLEAR_INBUFF            ;Clear input buffer
  1347. CM_20:
  1348.                 CALL    CHECK_CARRIER            ;Check for a connect signal
  1349.                 JZ        CM_30                    ;No, then check for err codes
  1350.                 CALL    CLEAR_SCREEN            ;Yes, blank the screen
  1351.                 MOV     BYTE PTR CONNECT_FLAG,1 ;Set the connect flag
  1352.                 JMP     CM_60                    ;Execute manned
  1353. CM_30:
  1354.                 MOV     AH,0                    ;Use input buffer
  1355.                 CALL    GET_BUFF_DATA            ;Get data from buffer
  1356.                 JNC     CM_20                    ;No data, try again
  1357.                 CMP     AL,"3"                    ;No carrier code?
  1358.                 JNZ     CM_50                    ;No, check for other code
  1359. CM_40:            
  1360.                 MOV     DX,OFFSET NO_CARRIER    ;Send no carrier message
  1361.                 MOV     AH,09H
  1362.                 INT     21H
  1363.                 JMP     CONNECT_MANNED            ;Yes, reset modem and try again
  1364. CM_50:
  1365.                 CMP     AL,"8"                    ;2400 no answer code
  1366.                 JZ        CM_40                    ;Yes, display no carrier mess
  1367.                 CMP     AL,"4"                    ;Error code?
  1368.                 JNZ     CM_20                    ;No, check for other code
  1369.                 MOV     DX,OFFSET MODEM_ERROR    ;Send modem command error mess
  1370.                 MOV     AH,09H
  1371.                 INT     21H
  1372.                 JMP     CONNECT_MANNED            ;Yes, reset modem and try again
  1373. CM_60:
  1374.                 MOV     AL,1                    ;Wait for a second
  1375.                 CALL    DELAY
  1376.                 MOV     BYTE PTR CR_COUNT,20D    ;Send 20 CRs at a time
  1377. CM_70:
  1378.                 CALL    CHECK_CARRIER            ;Check for carrier loss
  1379.                 JNZ     CM_80                    ;No, then continue
  1380.                 JMP     EXIT_MANNED             ;Yes, then exit
  1381. CM_80:
  1382.                 MOV     AX,OUT_BUFF_TAIL        ;Is output buffer empty?
  1383.                 CMP     AX,OUT_BUFF_HEAD
  1384.                 JNZ     CM_90                    ;No, skip CR
  1385.                 MOV     AL,CR                    ;Send a CR for speed sync
  1386.                 MOV     AH,1                    ;Use output buffer
  1387.                 CALL    PUT_BUFF_DATA
  1388.                 DEC     BYTE PTR CR_COUNT        ;Decrement CR counter
  1389.                 JZ        CM_60
  1390. CM_90:
  1391.                 MOV     AH,0                    ;Use input buffer
  1392.                 CALL    GET_BUFF_DATA            ; and check for data
  1393.                 JNC     CM_70                    ;No data so keep checking
  1394.                 CMP     AL,'@'                    ;Alpha message?
  1395.                 JL        CM_70                    ;No, then wait for it
  1396. CM_100:
  1397.                 CMP     AL,0                    ;Is data a sync byte
  1398.                 JNE     CM_110                    ;No, then put data on screen
  1399.                 CALL    CLEAR_SCREEN            ;Blank the screen
  1400.                 JMP     MANNED                    ;We're in, let's run program
  1401. CM_110:
  1402.                 MOV     DL,AL                    ;Prepare to display character
  1403.                 MOV     AH,2                    ; using DOS
  1404.                 INT     21H                     ;Display it
  1405. CM_120:
  1406.                 CALL    CHECK_CARRIER            ;Check for carrier loss
  1407.                 JNZ     CM_130                    ;No, then continue
  1408.                 JMP     EXIT_MANNED             ;Yes, then exit
  1409. CM_130:
  1410.                 CALL    GET_KEYSTROKE            ;Check for a keystroke
  1411.                 JZ        CM_150                    ;If none, skip next routine
  1412. ;
  1413. ;        Check for exit code, if it is then exit
  1414. ;
  1415.                 CMP     AX,WORD PTR EXIT_CODE    ;Check for exit code
  1416.                 JNZ     CM_140                    ;No, so continue
  1417.                 CALL    CONFIRM_EXIT            ;Yes, confirm exit
  1418.                 JNZ     CM_150                    ;No, so continue, don't send
  1419.                 JMP     EXIT_MANNED             ;Otherwise reset and exit
  1420. CM_140:
  1421.                 CALL    SEND_KEYSTROKE            ;Send to unattended system
  1422. CM_150:
  1423.                 MOV     AH,0                    ;Use input buffer
  1424.                 CALL    GET_BUFF_DATA            ; and check for data
  1425.                 JNC     CM_120                    ;No data, check for keys
  1426.                 JMP     CM_100                    ;Check for sync byte
  1427. CONNECT_MANNED    ENDP
  1428.  
  1429. ;----------------------------------------------------------------------
  1430. ;  Manned portion of the program.  Not RAM resident.  Sends keystrokes
  1431. ;  to the unattended computer.    Data from unattended computer is
  1432. ;  decoded and processed.
  1433. ;----------------------------------------------------------------------
  1434. MANNED            PROC    NEAR
  1435.                 ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1436. ;
  1437. ;        Check for loss of carrier
  1438. ;
  1439.                 CALL    CHECK_CARRIER            ;No, check for carrier loss
  1440.                 JNZ     M_10                    ;No loss so continue
  1441.                 JMP     EXIT_MANNED             ;Otherwise reset and exit
  1442. ;
  1443. ;        Check to see if shift status has changed, if so, put new status
  1444. ;        in the output buffer
  1445. ;
  1446. M_10:
  1447.                 MOV     AH,2                    ;Prepare to get shift status
  1448.                 INT     16H                     ;Get shift status
  1449.                 CMP     SHIFT_STATUS,AL         ;See if the same
  1450.                 JE        M_20                    ;If so then next routine
  1451.                 MOV     SHIFT_STATUS,AL         ;Save new status
  1452.                 MOV     AL,0FDH                 ;Sync byte, to expect shift
  1453.                 MOV     AH,1                    ;Put into output buffer
  1454.                 CALL    PUT_BUFF_DATA
  1455.                 MOV     AL,SHIFT_STATUS         ;Get the shift status
  1456.                 CALL    PUT_BUFF_DATA            ;Send to unattended computer
  1457. ;
  1458. ;        Check for keystoke, if so, put the ASCII code and scan code
  1459. ;        into the output buffer, check it for exit code
  1460. ;
  1461. M_20:
  1462.                 CALL    GET_KEYSTROKE            ;Check for keystroke
  1463.                 JZ        M_50                    ;If none skip this routine
  1464. ;
  1465. ;        Check for exit code, if it is then exit
  1466. ;
  1467.                 CMP     AX,WORD PTR EXIT_CODE    ;Check for exit code
  1468.                 JNZ     M_40                    ;No, so continue
  1469.                 CALL    CONFIRM_EXIT            ;Yes, confirm exit
  1470.                 JNZ     M_50                    ;No, so continue, don't send
  1471.                 JMP     EXIT_MANNED             ;Otherwise reset and exit
  1472. M_40:
  1473.                 CALL    SEND_KEYSTROKE            ;Send keystroke
  1474. ;
  1475. ;        Check for receive data, if available, get data and decode
  1476. ;
  1477. M_50:
  1478.                 MOV     AH,0                    ;Get data from input buffer
  1479.                 CALL    GET_BUFF_DATA
  1480.                 JC        M_60                    ;Data is there, so process
  1481.                 JMP     M_EXIT                    ;No data,so loop again
  1482. M_60:
  1483.                 CMP     BYTE PTR TYPE_TRANSFER,0FFH ;Check transfer type
  1484.                 JZ        M_100                    ;If ff, check for sync byte
  1485. M_70:
  1486.                 CMP     VID_RAM_OFFSET,0FFFFH    ;Received block no. yet?
  1487.                 JNZ     M_80                    ;Yes, then process as data
  1488.                 MOV     BYTE PTR BLOCK_DATA_COUNT,BLOCK_SIZE ;Data counter
  1489.                 MOV     BX,BLOCK_SIZEX2         ;Get block size in bytes
  1490.                 MUL     BX                        ;Block number X block size
  1491.                 ADD     AL,TYPE_TRANSFER        ;Adjust for char. or attr.
  1492.                 MOV     VID_RAM_OFFSET,AX        ;Save pointer to video RAM
  1493.                 JMP     M_EXIT
  1494. M_80:
  1495.                 MOV     DI,VID_RAM_OFFSET        ;Point to video RAM
  1496.                 CALL    PUT_VIDEO_DATA            ;Store the data in video RAM
  1497.                 INC     DI                        ;Point to next video RAM loc.
  1498.                 MOV     VID_RAM_OFFSET,DI          ;And save pointer
  1499.                 DEC     BYTE PTR BLOCK_DATA_COUNT ;Dec. data counter
  1500.                 JZ        M_90                      ;End of data, reset variables
  1501.                 JMP     M_EXIT                    ;Otherwise continue
  1502. M_90:
  1503.                 MOV     BYTE PTR TYPE_TRANSFER,0FFH ;Reset type transfer flag
  1504.                 JMP     M_EXIT
  1505. M_100:
  1506.                 CMP     BYTE PTR CUR_STATUS,0    ;Check cursor status
  1507.                 JZ        M_110                    ;If 0, check for sync byte
  1508.                 XOR     BX,BX                    ;Zero BX for index
  1509.                 MOV     BL,BYTE PTR CUR_STATUS    ;Use as index for cursor data
  1510.                 MOV     DI,OFFSET CUR_STATUS    ;Base address for cursor data
  1511.                 MOV     [DI+BX],AL                ;Save the register data
  1512.                 INC     BL                        ;Increment count
  1513.                 MOV     BYTE PTR CUR_STATUS,BL    ;And save it
  1514.  
  1515.                 CMP     BL,3                    ;Check to see if we have 3 byte
  1516.                 JNZ     M_EXIT                    ;No, so wait till enough data
  1517.                 MOV     BH,0                    ;Always use page one
  1518.                 MOV     DX,WORD PTR CUR_LOW     ;Get cursor position
  1519.                 MOV     AH,2                    ;Set cursor function
  1520.                 INT     10H
  1521.                 MOV     BYTE PTR CUR_STATUS,0    ;Reset cursor status
  1522.                 JMP     M_EXIT
  1523. M_110:
  1524.                 PUSH    AX                        ;Save the data
  1525.                 AND     AL,0FEH                 ;Mask out LSB
  1526.                 CMP     AL,0FEH                 ;Video data sync?
  1527.                 JNZ     M_120                    ;No, check for cursor sync
  1528.                 POP     AX                        ;Yes, restore data
  1529.                 AND     AL,1                    ;Save LSB
  1530.                 MOV     TYPE_TRANSFER,AL        ;Set transfer type flag
  1531.                 MOV     VID_RAM_OFFSET,0FFFFH    ;Prepare to receive block no.
  1532.                 JMP     M_EXIT
  1533. M_120:
  1534.                 CMP     AL,0D2H                 ;Check for cursor data sync
  1535.                 JNZ     M_130                    ;If not, then throw away
  1536.                 POP     AX                        ;Restore data
  1537.                 MOV     BYTE PTR CUR_STATUS,1    ;Set cursor status byte
  1538.                 JMP     M_EXIT
  1539. M_130:
  1540.                 POP     AX                        ;Clean up stack
  1541. M_EXIT:
  1542.                 JMP     MANNED                    ;Do it again
  1543. MANNED            ENDP
  1544.  
  1545. ;----------------------------------------------------------------------
  1546. ;  Exit manned.  The exit code is sent, interrupt vector reset, and
  1547. ;  the modem is hung up and reset
  1548. ;  Input - Nothing
  1549. ;  Output - DOS
  1550. ;  Changes - everything
  1551. ;----------------------------------------------------------------------
  1552. EXIT_MANNED     PROC    NEAR
  1553.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1554.                 MOV     AX,WORD PTR EXIT_CODE    ;Get the exit code
  1555.                 CALL    SEND_KEYSTROKE            ;Send the exit code
  1556.                 CALL    CLEAR_SCREEN            ;Blank the screen
  1557.                 MOV     DX,OFFSET TERMINATE_MESS;Display terminate call msg
  1558.                 MOV     AH,09H
  1559.                 INT     21H
  1560.                 XOR     AL,AL                    ;Reset modem and exit
  1561.                 CALL    RESET_MODEM
  1562.                 MOV     AL,1                    ;Wait a second
  1563.                 CALL    DELAY
  1564. ;
  1565. ;  Disable the serial port interrupts and reset the 8259 mask
  1566. ;
  1567.                 MOV     DX,COMM_PORT            ;Get port address
  1568.                 INC     DX                        ;Interrupt enable reg.
  1569.                 XOR     AL,AL
  1570.                 OUT     DX,AL                    ;Disable all interrupts
  1571.                 CMP     BYTE PTR COMM_FLAG,0    ;Determine mask bit to change
  1572.                 JZ        EM_10
  1573.                 MOV     BL,00001000B            ;Mask for 8259 COM2
  1574.                 JMP     EM_20
  1575. EM_10:
  1576.                 MOV     BL,00010000B            ;Mask for 8259 COM1
  1577. EM_20:
  1578.                 IN        AL,21H                    ;Get current 8259 int mask
  1579.                 OR        AL,BL                    ;Set appropriate int bit
  1580.                 OUT     21H,AL                    ;And set new 8259 mask
  1581.                 INT     20H                     ;Terminate program
  1582. EXIT_MANNED     ENDP
  1583.  
  1584. ;----------------------------------------------------------------------
  1585. ;  Clear screen.  This routine will blank the video display
  1586. ;  Input - Nothing
  1587. ;  Output - Screen is cleared
  1588. ;  Changes - AX, BX, CX, DX
  1589. ;----------------------------------------------------------------------
  1590. CLEAR_SCREEN    PROC    NEAR
  1591.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1592.                 MOV     BX,0                    ;Use video page one
  1593.                 MOV     DX,0                    ;Position cursor at row 0 col 0
  1594.                 MOV     AH,2                    ;Set cursor function
  1595.                 INT     10H
  1596.                 MOV     AX,0700H                ;Scroll down, clear screen
  1597.                 MOV     BH,07H                    ;White on black
  1598.                 MOV     CX,0                    ;Upper left corner
  1599.                 MOV     DH,24D                    ;Lower right corner
  1600.                 MOV     DL,79D
  1601.                 INT     10H                     ;Video BIOS call
  1602.                 RET
  1603. CLEAR_SCREEN    ENDP
  1604.  
  1605. ;----------------------------------------------------------------------
  1606. ;  Store the video data in AL in the memory location pointed to by DI
  1607. ;  Input - AL video data, ES:DI video RAM destination
  1608. ;  Output - Nothing
  1609. ;  Changes - DI is incremented
  1610. ;----------------------------------------------------------------------
  1611. PUT_VIDEO_DATA    PROC    NEAR
  1612.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1613. ;
  1614. ;        Check desnow flag, if set wait for horizontal sync to put in video RAM
  1615. ;
  1616.                 PUSH    BX                        ;Save registers
  1617.                 PUSH    DX
  1618.                 CMP     BYTE PTR DESNOW_FLAG,0    ;Check desnow flag
  1619.                 JZ        PV_30                    ;No, skip over
  1620.                 CLD                             ;Forward
  1621.                 MOV     BL,AL                    ;Save video data
  1622.                 MOV     DX,3DAH                 ;CGA status port
  1623.                 CLI                             ;Disable interrupts
  1624. PV_10:
  1625.                 IN        AL,DX                    ;Get status byte
  1626.                 TEST    AL,1                    ;Test display enable
  1627.                 JNZ     PV_10                    ;If in Hor. sync then wait
  1628. PV_20:
  1629.                 IN        AL,DX                    ;Get status byte
  1630.                 TEST    AL,1                    ;Test display enable
  1631.                 JZ        PV_20                    ;Wait for Hor. sync
  1632.                 XCHG    AX,BX                    ;Get video data
  1633. PV_30:
  1634.                 STOSB                            ;And put into video RAM
  1635.                 STI                             ;Enable interrupts
  1636.                 POP     DX                        ;Restore registers
  1637.                 POP     BX
  1638.                 RET
  1639. PUT_VIDEO_DATA    ENDP
  1640.  
  1641. ;----------------------------------------------------------------------
  1642. ;  Display OK to exit message and wait for response
  1643. ;  Input - Nothing
  1644. ;  Output - Zero flag set - exit, zero flag reset - do not exit
  1645. ;  Changes - CX, SI, DI
  1646. ;----------------------------------------------------------------------
  1647. CONFIRM_EXIT    PROC    NEAR
  1648.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1649.                 PUSH    AX                        ;Save the exit code
  1650. CE_10:
  1651.                 MOV     AX,OUT_BUFF_HEAD        ;Wait until the out buffer
  1652.                 CMP     AX,OUT_BUFF_TAIL        ; is empty
  1653.                 JNZ     CE_10
  1654. ;
  1655. ;  Save the existing video data in the output buffer
  1656. ;
  1657.                 CALL    SWITCH_DS_ES
  1658.                 MOV     DI,ES:OUT_BUFF_BEGIN    ;Use output buffer as temp stor.
  1659.                 MOV     SI,0                    ;Upper left corner of video
  1660.                 MOV     CX,3                    ;Transfer 3 lines
  1661. CE_20:
  1662.                 PUSH    CX                        ;Save line counter
  1663.                 MOV     CX,20D                    ;Transfer 20 char. per line
  1664.                 REPNZ    MOVSW
  1665.                 ADD     SI,120D                 ;Next line
  1666.                 POP     CX                        ;Restore line counter
  1667.                 LOOP    CE_20
  1668. ;
  1669. ;  Display the ok to exit message
  1670. ;
  1671.                 CALL    SWITCH_DS_ES
  1672.                 MOV     DI,0                    ;Upper left corner of video
  1673.                 MOV     SI,OFFSET EXIT_MESSAGE    ;Exit message
  1674.                 MOV     CX,3                    ;Display three lines
  1675. CE_30:
  1676.                 PUSH    CX                        ;Save line counter
  1677.                 MOV     CX,20D                    ;Display 20 characters per line
  1678. CE_40:
  1679.                 LODSB
  1680.                 CALL    PUT_VIDEO_DATA            ;Display the character
  1681.                 MOV     AL,7                    ;White on black attribute
  1682.                 CALL    PUT_VIDEO_DATA            ;Store attribute
  1683.                 LOOP    CE_40
  1684.                 ADD     DI,120D                 ;Next line
  1685.                 POP     CX                        ;Restore line counter
  1686.                 LOOP    CE_30
  1687. ;
  1688. ;  Wait for keystroke and convert to lower case
  1689. ;
  1690. CE_50:
  1691.                 CALL    GET_KEYSTROKE            ;Check for keystroke
  1692.                 JZ        CE_50                    ;None there, try again
  1693.                 OR        AL,20H                    ;Convert to lower case
  1694. ;
  1695. ;  Restore the saved video data
  1696. ;
  1697.                 MOV     SI,OUT_BUFF_BEGIN        ;Old video is in output buffer
  1698.                 MOV     DI,0                    ;Upper left corner of video
  1699.                 MOV     CX,3                    ;Transfer 3 lines
  1700. CE_60:
  1701.                 PUSH    CX                        ;Save line counter
  1702.                 MOV     CX,20D                    ;Transfer 20 char. per line
  1703.                 REPNZ    MOVSW
  1704.                 ADD     DI,120D                 ;Next line
  1705.                 POP     CX                        ;Restore line counter
  1706.                 LOOP    CE_60
  1707.                 CMP     AL,'y'                    ;Check for yes, all others no
  1708.                 POP     AX                        ;Restore exit code
  1709.                 RET
  1710. CONFIRM_EXIT    ENDP
  1711.  
  1712. ;----------------------------------------------------------------------
  1713. ;  Switch ES and DS
  1714. ;  Input - Nothing
  1715. ;  Output - ES is in DS and DS is in ES
  1716. ;  Changes - ES, DS
  1717. ;----------------------------------------------------------------------
  1718. SWITCH_DS_ES    PROC    NEAR
  1719.                 PUSH    ES
  1720.                 PUSH    DS
  1721.                 POP     ES
  1722.                 POP     DS
  1723.                 RET
  1724. SWITCH_DS_ES    ENDP
  1725.  
  1726. ;----------------------------------------------------------------------
  1727. ;  Put the keystroke data into the output buffer to be sent to unattended
  1728. ;  system
  1729. ;  Input - AX - keystroke data
  1730. ;  Output - Nothing
  1731. ;  Changes - Nothing
  1732. ;----------------------------------------------------------------------
  1733. SEND_KEYSTROKE    PROC    NEAR
  1734.         ASSUME    CS:CSEG,DS:CSEG,ES:NOTHING,SS:NOTHING
  1735.                 PUSH    AX                        ;Save it
  1736.                 MOV     AH,1                    ;Use the output buffer
  1737.                 MOV     AL,0FEH                 ;Sync byte, to expect key data
  1738.                 CALL    PUT_BUFF_DATA            ;Put AL into the output buffer
  1739.                 POP     AX                        ;Get AL back
  1740.                 PUSH    AX                        ;Save AH
  1741.                 MOV     AH,1                    ;Use the output buffer
  1742.                 CALL    PUT_BUFF_DATA            ;Put ASCII code in out buffer
  1743.                 POP     AX                        ;Get AH back
  1744.                 PUSH    AX                        ;Save keystroke
  1745.                 MOV     AL,AH                    ;Move it to AL
  1746.                 MOV     AH,1                    ;Use the output buffer
  1747.                 CALL    PUT_BUFF_DATA            ;Put scan code in out buffer
  1748.                 POP     AX                        ;Restore keystroke
  1749.                 RET
  1750. SEND_KEYSTROKE    ENDP
  1751.  
  1752. ;======================================================================
  1753. LAST_BYTE        EQU     $
  1754. CSEG            ENDS
  1755.                 END     START
  1756.