           PAGE    62,132 
           Title   DoubleDOS Utility: SEND Commands 

CR                 EQU     0Dh                   ;ASCII Carriage Return
LF                 EQU     0Ah                   ;ASCII Line Feed
$                  EQU     24h                   ;String termination charachter

Parm_Byte_Count    EQU     80h

Dos_Call           EQU     21h
Terminate_Process  EQU     4Ch
Display_Character  EQU     02h
Put_String         EQU     09h

DD_Menu_Control    EQU     0E0h
Resume_Invisible   EQU     73h
Suspend_Invisible  EQU     75h
DD_Send_Char       EQU     0E2h
DD_Other_Status    EQU     0E5h
Give_Other_Time    EQU     0EEh

Print_$    MACRO
           mov     ah,Put_String
           int     Dos_Call
           ENDM

Code_Seg   SEGMENT 
           ASSUME  cs:Code_Seg,ds:Code_Seg,es:Code_Seg
           ORG     0100h  
Main       PROC    NEAR

           mov     si,Parm_Byte_Count            ;Point to parm byte count 
           mov     di,OFFSET Parm_Copy           ;point to copy destination
           cld                                   ;  String Counts forward
           lodsb                                 ;  AL = Byte Count

           mov     Parm_Count,al                 ;Store Byte Count 
           mov     dx,OFFSET Prog_Info           ;Display program info
           PRINT_$
           mov     al,Parm_Count                 ;Restore Byte Count

           cmp     al,00h
           jz      Err_Chk1                      ;No parms given?
           test    al,80h
           jnz     Err_Chk2                      ;More than 127 bytes?

           cbw                                   ;AX = Byte Count
           mov     cx,ax                         ;CX = Loop control
           rep     movsb                         ;Copy parms into buffer

           mov     dx,OFFSET Send_Msg            ;Sending...
           Print_$


           call    Chk_Susp                      ;Other partition Suspended?


           mov     al,Parm_Count                 ;Get Char Count
           cbw
           mov     cx,ax                         ;Convert to word in CX
           mov     si,OFFSET Parm_Copy           ;Prepare to Send chars
           inc     si                            ;Throw away 1st char
           dec     cx                            ;  also lower cnt by 1

Send_Loop: mov     al,BYTE PTR [si]
           mov     pending,al                    ;Charachter to be sent
           mov     Retry_Cnt,03h                 ;3 Retries in case of Err
           mov     Temp_Cnt,cx                   ;Save Count
           call    Send_Char                     ;Send character

           mov     ah,Display_Character          ;If control was returned,
           mov     dl,Pending                    ;  all went well. Output
           int     Dos_Call                      ;  charachter

           mov     cx,Temp_Cnt                   ;Restore Count
           dec     cx                            ;Decrement Count
           inc     si
           jcxz    Exit_Loop                     ;Done?
           jmp     Send_Loop                     ;No, Next Char

Exit_Loop: mov     Pending,CR                    ;Follow with Carriage Return
           mov     Retry_Cnt,03h                 ;3 Tries
           call    Send_Char

           mov     dx,OFFSET CRLF
           Print_$


           call    Fix_Susp                      ;Suspend the other partition
                                                 ;  if we have temporarily
                                                 ;resumed it.

           
           mov     Ret_Code,30h                  ;All Kosher, end program
           jmp     Finished                      ;Return ERRORLEVEL 0


;//////////////////
;
;  Error Checking Routines
;
;//////////////////

Err_Chk1:  mov     dx,OFFSET Err_Msg1
           Print_$
           mov     Ret_Code,39h                  ;Return ERRORLEVEL 9
           jmp     Finished

Err_Chk2:  mov     dx,OFFSET Err_Msg2
           Print_$
           mov     Ret_Code,38h                  ;Return ERRORLEVEL 8
           jmp     Finished                      

Err_Chk3:  mov     dx,OFFSET ERR_Msg3
           Print_$
           mov     Ret_Code,37h                  ;Return ERRORLEVEL 7
           call    Fix_Susp
           jmp     Finished

Err_Chk4:  mov     dx,OFFSET ERR_Msg4
           Print_$
           mov     Ret_Code,36h                  ;Return ERRORLEVEL 6
           call    Fix_Susp
           jmp     Finished

;//////////////////
;
;    This Routine Actually sends a charachter to the other side, with
;  full error checking.  Err_Chk3 is an unknown error.  Err_Chk4 means
;  the keyboard buffer on the other side is full.
;
;//////////////////

Send_Char: mov     al,Pending                    ;Get Char
           mov     ah,DD_Send_Char
Retry:     int     Dos_Call                      ;Send it
           cmp     al,00h
           jnz     Problem                       ;Successfully Sent?
           ret                                   ;Yes.

Problem:   cmp     al,01                         ;No.
           jz      Buff_Full                     ;Buffer full?
           jmp     Err_Chk3                      ;No, Terminate program

Buff_Full: mov     al,Retry_Cnt
           cmp     al,00h
           jz      Err_Chk4                      ;3 Tries, Terminate
           dec     Retry_Cnt                     ;1 less try

           mov     al,0FFh                       ;Give the other side
           mov     ah,Give_Other_Time            ;  time to think: 255
           int     Dos_Call                      ;  55ms time intervals
           mov     al,Pending                    ;restore Charachter
           jmp     Retry                         ;Try Again

Finished:  mov     dx,OFFSET Finish_Msg          ;Display ERRORLEVEL MSG
           PRINT_$
           mov     ah,Terminate_Process          ;End Program
           mov     al,Ret_Code                   ;ERRORLEVEL in AL
           and     al,0Fh                        ;Ascii to binary integer
           int     Dos_Call


;//////////////////
;
;    This subroutine checks to see if the other partition is suspended.
;  If it is, we RESUME it, and set a flag telling the program to re-suspend
;  the other partition prior to termination.
;
;//////////////////

Chk_Susp:  mov     ah,DD_Other_Status
           int     Dos_Call
           mov     Suspended,00h
           cmp     al,02h                    
           jz      Resume                        ;Other side Suspended?
           ret                                   ;No

Resume:    mov     Suspended,01h                 ;Yes: Flag for later,
           mov     ah,DD_Menu_Control            ;     and Resume
           mov     al,Resume_Invisible
           int     Dos_Call
           ret


;//////////////////
;
;    This routine checks to see if the other partition was suspended when
;  this program was executed. If we temporarily resumed it, then we
;  re-suspend it.
;
;//////////////////
  
Fix_Susp:  mov     al,Suspended                  ;Was Other side Suspended
           cmp     al,00h                        ;  then Resumed?
           jnz     Susp
           ret                                   ;No

Susp:      mov     ah,DD_Menu_Control            ;Yes, Re-Suspend
           mov     al,Suspend_Invisible
           int     Dos_Call
           ret


;//////////////////
;
;  Data Definition Area
;
;//////////////////

Prog_Info  DB      CR,LF,'DoubleDOS Utility - by Chris M. Magyar '
           DB      '- 12/18/85',CR,LF,CR,LF,$

Send_Msg   DB      'The following command will be sent '
           DB      'to the other partition:',CR,LF,CR,LF,$

Finish_Msg DB      CR,LF,'ERRORLEVEL : '
Ret_Code   DB      ?,' being returned.',CR,LF,$

Err_Msg1   DB      'No parameters given.',CR,LF,$
Err_Msg2   DB      'More than 127 bytes in parameter list!!!',CR,LF
           DB      'Must terminate now.',CR,LF,$
Err_Msg3   DB      'Unknown Error encountered when passing character',CR,LF
           DB      'to the other partition.  Must Terminate now.',CR,LF,$
Err_Msg4   DB      'The keyboard buffer on the other partition is',CR,LF
           DB      'full.  All re-tries failed.  Terminating now.',CR,LF,$

CRLF       DB      CR,LF,$

Parm_Count DB      ?
Parm_Copy  DB      128 DUP(?),CR,LF,$

Suspended  DB      ?
Pending    DB      ?
Retry_Cnt  DB      ?
Temp_Cnt   DW      ?

Main       ENDP
Code_Seg   ENDS
           END Main

