	PAGE 59, 132

	TITLE MSRECV -- Module to Receive a file

; Update 13 Jan 86

IF1
 %OUT >> Starting pass 1
ELSE
 %OUT >> Starting pass 2
ENDIF

    PUBLIC Read1, Read2, rin21, rfile3, read, updrtr, nak, rrinit

    INCLUDE MsDefs.H	

DataS	SEGMENT	PUBLIC 'DataS'

    EXTRN fcb:byte, data:byte, bufpnt:word, chrcnt:word, curchk:byte
    EXTRN comand:byte, flags:byte, pack:byte, trans:byte, OFilSz:WORD

ermes7  DB 'Unable to Receive Initiate$'
ermes8  DB 'Unable to receive file name$'
ermes9  DB 'Unable to receive end of file$'
erms10  DB 'Unable to receive data$'
erms11  DB 'Unable to receive attribute or data$'
erms12  DB 'Not enough room on disk for file$'
ermes7a DB 'Remote '
	Program_name
	DB ': Unable to receive initiate$'
ermes8a DB 'Remote '
	Program_name
	DB ': Unable to receive file name$'
ermes9a DB 'Remote '
	Program_name
	DB ': Unable to receive end of file$'
erms10a DB 'Remote '
	Program_name
	DB ': Unable to receive data$'
erms11a DB 'Remote '
	Program_name
	DB ': Unable to receive attribute or data$'
erms12a	DB 'Remote '
	Program_name
	DB ': Not enough room on disk for file$'
infms1  DB cr,'           Receiving: In progress$'
infms3  DB 'Completed$'
infms4  DB 'Failed$'
infms6  DB 'Interrupted$'
infms7	DB cr,' Percent transferred: 100%$'
filhlp2 DB ' Confirm with carriage return, or specify name '
	DB 'to use for incoming file$'
crlf	DB cr,lf,'$'
temp	dw	0
ATR_KBytes DW	0		; File size in K, according to file's sender
ATR_Avail DW	0		; Free space on disk, in K
ATR_Ptr	DW	0		; Ptr to reading point in attribute string
ATR_End_ptr DW	0		; Ptr to point we don't read from
ATR_Length DW	0		; Number of chars in attribute data subfield
ATR_Attribute DB 0		; ASCII char representing attribute type

SPC_Msg1 DB 'The incoming file requires $'
SPC_Msg2 DB ' K bytes of disk space, but$'
SPC_Msg3 DB 'the disk you are using has only $'
SPC_Msg4 DB ' K bytes available.$'
SPC_Msg5 DB 'Please insert a formatted disk which'
	 DB ' has enough room for this file.$'
SPC_Msg7 DB 'Type control-C to ABORT, any other key to try a new disk.$'

SPC_Addr1 EQU (15*256)+5	; Locations for messages
SPC_Addr3 EQU (16*256)+5
SPC_Addr5 EQU (18*256)+5
SPC_Addr7 EQU (20*256)+5

datas	ends

Code	SEGMENT	PUBLIC

    EXTRN gofil:near, outbuf:near, fixfcb:near, comnd:near, EOT_bells:NEAR
    EXTRN spack:near, rpack:near, serini:NEAR, Nout:NEAR, poscur:near
    EXTRN spar:near, rpar:near, init:near, init1:near, cxmsg:near
    EXTRN error:near, ptchr:near, PerPos:near, ClearL:near
    EXTRN dodec:near, doenc:near, errpack:near, beep:near
    EXTRN ClrMod:near, Close_transfer_screen:NEAR, Show_packets:NEAR
    EXTRN Show_error:NEAR, Show_status:NEAR, Show_retries:NEAR
    EXTRN Clear_percent_message:NEAR

    ASSUME cs:Code, ds:DataS

 
; Update retry count and fall through to send a NAK
nak0:	call updrtr		; Update retry count

nak:	mov ax,pack.pktnum	; Get the packet number we're waiting for
	mov pack.argblk,ax
	mov pack.argbk1,0
	mov cx,0		; No data, but this may change
	call doenc		; So call encode
	mov ah,'N'		; NAK that packet
	call Spack
	 jmp Abort

	ret

updrtr:	cmp pack.state,'A'	; Supposed to abort?
	je upd0			; Yes, don't bother with retry count
	inc pack.numrtr		; Increment the number of retries
	cmp flags.xflg,1	; Writing to screen?
	je upd0

	call Show_retries	; Use common routine

upd0:	ret


; init variables for read..
rrinit	proc	near
	mov pack.numpkt,0	; Set the number of packets to zero
	mov pack.numrtr,0	; Set the number of retries to zero
	mov pack.pktnum,0	; Set the packet number to zero
	mov pack.numtry,0	; Set the number of tries to zero
	ret
rrinit	endp

;	RECEIVE command  --  Some code moved to the GET routine. [21a] 
 
READ	PROC	NEAR		
	mov comand.cmrflg,1	; Say we're receiving a file. [21a start]
	mov comand.cmcr,1	; Allow bare CR after RECEIVE
	mov flags.droflg,0	; Override default drive flag
	mov flags.nmoflg,0	; Override file name from other host?
	mov dx,offset fcb	; Put filename here. 
	mov bx,offset filhlp2	; Text of help message
	mov ah,cmifi		; Read in the filename
	call comnd		
	 jmp RSkp
	mov comand.cmrflg,0	; Reset flag
	mov comand.cmcr,0
	mov flags.wldflg,0	; Just in case
	mov ah,cmcfm		; Get a confirm
	call comnd
	 jmp r

	mov pack.state,'R'	; Set the state to receive initiate
	call Init		; Clear the screen, put up FT screen
	call rrinit		; init variables for read
	call serini		; Initialize serial port. [14]

	call Read1		; Call our routine to do the receive
	 nop			;  He skips usually
	 nop
	 nop

	jmp RSkp		; Return skip to main KERMIT loop


; Routine to perform a RECEIVE of a file (called from here and from MSSERV)

Read1:	mov flags.cxzflg,0	; Reset ^X/^Z flag. [20c] 
	call init1		; Clear the line and initialize the buffers

	mov dx, OFFSET infms1	; "Receiving: In progress"
	call Show_status	; Display status

	call Show_packets	; Display packet count
	call ClearL		; Make sure display looks right

	call Show_retries	;  and number of retries
	call ClearL		; Likewise

read2:	cmp flags.xflg,1	; Are we receiving to the screen. [21c]
	 je read21		; Skip the screen stuff. [21c]

	call Show_packets	; Display the packet count

read21: mov ah,pack.state	; Get the state. [21c]
	cmp ah,'T'		; Are we in the aTtribute state?
	jne read23
	call RAttr		; Waiting for attribute packet or data
	jmp read2
read23:	cmp ah,'D'		; Are we in the Data receive state?
	jne read3
	call rdata
	jmp read2
read3:  cmp ah,'F'		; Are we in the file receive state?
	jne read4
	call rfile		; Call receive file
	jmp read2
read4:  cmp ah,'R'		; Are we in the receive initiate state?
	jne read5
	call rinit
	jmp read2

Read5:  cmp ah,'C'		; Are we in the receive complete state?
	 jne read6

	cmp flags.xflg,0	; Did we write to the screen? [21c]
	 je Read5a		; No so print status. [21c]

	mov Flags.xflg, 0	; Reset it. [21c]
	jmp RSkp		; Yes, so just return. [21c]

Read5a:	cmp Flags.RemFlg,0	; Remote mode?
	 jne Read7a		;  Yes, don't type anything

	cmp Flags.cxzflg, 0	; completed normally?
	 jne Read5b		;  no, don't bother with this

	call PerPos		; Note that we are now 100% done
	mov ah, PrStr
	mov dx, OFFSET infms7
	int Dos

	mov dx, OFFSET InfMs3	; Message saying success
	jmp SHORT Read5c

Read5b: mov dx, OFFSET infms6	; Say was interrupted

Read5c: call Show_status	; Display the message, whatever it is
	call EOT_bells		; Make optional noise
	jmp SHORT Read7

; Here, we have some type of error -- clean up and go home

read6:	cmp flags.xflg,0	; Did we write out to screen? [21c]
	 je read61		; No so print status. [21c]
	mov flags.xflg,0	; Reset it. [21c]
	jmp rskp		; Print onto screen. [21c]

read61:	mov dx,offset infms4	; Plus a little cuteness
	call Show_status

read7:	call Close_transfer_screen ; Clean up for command mode

read7a:	jmp rskp

READ	ENDP
 
 
;	Receive routines
 
;	Receive init
 
RINIT	PROC	NEAR
	mov ah,pack.numtry	; Get the number of tries
	cmp ah,imxtry		; Have we reached the maximum number of tries?
	jl rinit2
	mov dx,offset ermes7
	call Show_error		; Display message
	mov bx,offset ermes7a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort
rinit2: inc ah			; Increment it
	mov pack.numtry,ah	; Save the updated number of tries
	mov ax,pack.argbk2	; get packet type if here from get
	cmp flags.getflg,1	; Have we already read in the packet? [21a] 
	je rin21a		; Yes, so don't call RPACK. [21a]
	mov ah,trans.chklen
	mov curchk,ah		; Save checksum length we want to use
	mov trans.chklen,1	; Use 1 char for init packet
	call rpack		; Get a packet
	 jmp rin22		; Trashed packet: nak, retry
	push ax
	mov ah,curchk
	mov trans.chklen,ah	; Reset to desired value
	pop ax
rin21a:	cmp ah,'S'		; Is it a send initiate packet?
	jne rinit3		; If not see if its an error
rin21:	mov flags.getflg,0	; Reset flag. [21a]
	mov ah,pack.numtry	; Get the number of tries
	mov pack.oldtry,ah	; Save it
	mov pack.numtry,0	; Reset the number of tries
	mov ax,pack.argblk	; Returned packet number.  (Synchronize them.)
	inc ax			; Increment it
	and ax,3FH		; Turn off the two high order bits
	mov pack.pktnum,ax	; Save modulo 64 of the number
	mov bx,pack.numpkt
	inc bx			; Increment the number of packets
	mov pack.numpkt,bx
	mov ax,pack.argbk1	; Get the number of arguments received
	mov bx,offset data	; Get a pointer to the data
	call spar		; Get the data into the proper variables
	mov bx,offset data	; Get a pointer to our data block
	call rpar		; Set up the receive parameters
	xchg ah,al
	mov ah,0
	mov pack.argbk1,ax	; Store the returned number of arguments
	mov ah,trans.chklen	; Checksum length we'll use
	mov curchk,ah		; Save it
	mov trans.chklen,1	; Use 1 char for init packet
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort
	mov ah,curchk		; Checksum length we'll use
	mov trans.chklen,ah	; Reset to desired value
	mov ah,'F'		; Set the state to file send
	mov pack.state,ah
	ret
rin22:	mov ah,curchk
	mov trans.chklen,ah	; Reset to desired value
	jmp nak0		; Try again
rinit3: cmp ah,'E'		; Is it an error packet?
	jne rinit4
	call error
rinit4:	jmp abort
RINIT	ENDP
 

;	Receive file
 
RFILE	PROC	NEAR
	cmp pack.numtry,maxtry	; Have we reached the maximum number of tries?
	jl rfile1
	mov dx,offset ermes8
	call Show_error		; Display message
	mov bx,offset ermes8a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort
rfile1: inc pack.numtry		; Save the updated number of tries
	call rpack		; Get a packet
	 jmp nak0		;  Trashed packet: nak, retry
	cmp ah,'S'		; Is it a send initiate packet?
	je rfil10
	call dodec		; Decode all incoming packets
	jmp rfile2		;  No, try next type
rfil10:	cmp pack.oldtry,imxtry	; Have we reached the maximum number of tries?
	jl rfil12		; If not proceed
	mov dx,offset ermes7
	call Show_error		; Display message
	mov bx,offset ermes7a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort

%OUT >> About half way through source file

rfil12: inc pack.oldtry		; Save the updated number of tries
	mov ax,pack.pktnum	; Get the present packet number
	cmp ax,0		; Had we wrapped around? [18 start]
	jne rfilx 
	mov ax,64
rfilx:  dec ax			; Decrement.  [18 end -- new label]
	cmp ax,pack.argblk	; Is the packet's number one less than now?
	je rfil13
	jmp nak0		; No, NAK and try again
rfil13: call updrtr		; Update retry count
	mov pack.numtry,0	; Reset the number of tries
	mov bx,offset data	; Get a pointer to our data block
	call rpar		; Set up the parameter information
	xchg ah,al
	mov ah,0
	mov pack.argbk1,ax	; Save the number of arguments
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort
	ret
rfile2: cmp ah,'Z'		; Is it an EOF packet?
	jne rfile3		;  No, try next type
	cmp pack.oldtry,maxtry	; Have we reached the maximum number of tries?
	jl rfil21		; If not proceed
	mov dx,offset ermes9
	call Show_error		; DIsplay message
	mov bx,offset ermes9a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort
rfil21: inc pack.oldtry		; Increment it
	mov ax,pack.pktnum	; Get the present packet number
	cmp ax,0		; Had we wrapped around? [18 start]
	jne rfily
	mov ax,64
rfily:  dec ax			; Decrement.  [18 end -- new label]
	cmp ax,pack.argblk	; Is the packet's number one less than now?
	je rfil24
	jmp nak0		; No, NAK and try again
rfil24: call updrtr		; Update retry count
	mov pack.numtry,0
	mov pack.argbk1,0	; No data.  (The packet number is in argblk.)
	mov cx,0
	call doenc
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort
	ret
rfile3: cmp ah,'F'		; Start of file?
	je rfil31		; Yes. [21c]
	cmp ah,'X'		; Text header packet? [21c]
	jne rfile4		; Neither one. 
rfil31: mov ax,pack.argblk	; Get the packet number. [21c]
	cmp ax,pack.pktnum	; Is it the right packet number?
	je rfil32
	jmp nak			; No, NAK it and try again
rfil32: inc ax			; Increment the packet number
	and ax,3FH		; Turn off the two high order bits
	mov pack.pktnum,ax	; Save modulo 64 of the number
	inc pack.numpkt		; Increment the number of packets
	call gofil		; Get a file to write to
	 jmp abort
	call init1		; Initialize all the buffers
	mov ah,pack.numtry	; Get the number of tries
	mov pack.oldtry,ah	; Save it
	mov pack.numtry,0	; Reset the number of tries
	mov pack.argbk1,0	; No data.  (The packet number is in argblk.)

	call Clear_percent_message ; Erase this for now

	mov cx,0
	call doenc
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort

;	mov pack.state,'D'
	mov pack.state,'T'	; Set the state to waiting for aTtribute

	ret
rfile4: cmp ah,'B'		; End of transmission
	jne rfile5
	mov ax,pack.pktnum
	cmp ax,pack.argblk	; Do we match?
	je rfil41
	jmp nak			; No, NAK it and try again
rfil41: mov pack.argbk1,0	; No data.  (Packet number already in argblk)
	mov cx,0
	call doenc
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort
	mov pack.state,'C'	; Set the state to complete
	ret
rfile5: cmp ah,'E'		; Is it an error packet
	jne rfile6
	call error
rfile6: jmp abort
RFILE	ENDP
 
 
;	Receive attribute or data

	PUBLIC RAttr, rdat11, ATR_2, ATR_3, ATR_5, ATR_err

RAttr	PROC

	cmp pack.numtry,maxtry	; Get the number of tries
	 jae ATR_err		;  Too many errors, go blow up

	inc pack.numtry		; Save the updated number of tries
	call rpack		; Get a packet
	 jmp nak0		;  Trashed packet: nak, retry

	cmp ah,'D'		; Is it a data packet?
	 jne ATR_2		;  No, see if it is an Attribute packet

; Deal with Data (D) packet

	mov pack.state, 'D'	; Switch to Data state
	jmp rdat11		; Go join the RDATA routine

ATR_2:	cmp ah, 'A'		; Attribute packet?
	 je ATR_3		;  Yes

	jmp rdata2		; No, use RDATA code to see what it is

; Deal with Attribute (A) packet

ATR_3:	mov ax,pack.pktnum	; Get the present packet number
	cmp ax,pack.argblk	; Is the packet's number correct?
	 je ATR_7		;  Yes

; Got the wrong packet number

	cmp pack.oldtry,maxtry	; Have we reached the maximum number of tries?
	 jae ATR_err		;  Too many errors

	inc pack.oldtry		; Save the updated number of tries

	mov ax,pack.pktnum
	cmp ax,0		; Had we wrapped around? [18 start]
	 jne ATR_5

	mov ax,64

ATR_5:	dec ax			; [14] [18 end -- new label]
	cmp ax,pack.argblk	; Is the packet's number one less than now?
	 je ATR_6		;  Yes

	jmp nak0		; No, NAK it and try again

; File sender has sent us a second copy of a packet we already ACKed,
;  which suggests that our ACK was lost.  Send another ACK so we can move
;  on to the next packet.  This constitutes a retry

ATR_6:	call updrtr		; Update retry count

	mov pack.numtry,0	; Reset number of tries
	mov pack.argbk1,0	; No data.  (The packet number is in argblk.)
	mov cx,0

	call doenc

	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort

	ret

; Common point for error, Too many retries

ATR_err:
	mov dx,offset erms11
	call Show_error		; Display message
	mov bx,offset erms11a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort

	PUBLIC ATR_7, ATR_8, ATR_9, ATR_10, ATR_LP1, ATR_Ignore
	PUBLIC ATR_Do_filesize

; Have good Attribute packet, the right packet number and everything

ATR_7:	inc ax			; Increment the packet number
	and ax,3FH		; Turn off the two high order bits
	mov pack.pktnum,ax	; Save modulo 64 of the number

	inc pack.numpkt		; Increment the number of packets

	mov ah,pack.numtry	; Get the number of tries
	mov pack.oldtry,ah	; Save it

; Interrupted?

	mov ax,pack.argbk1	; Get the length of the data
	cmp flags.cxzflg,0	; Has the user typed a ^X or ^Z? [20c]
	 je ATR_8		;  No, keep dealing with Attribute packet

	cmp flags.abfflg,1	; Discard incomplete files?
	 je ATR_9		;  If yes don't write data out to file

; Process the attribute(s) in the packet

ATR_8:	mov ax, OFFSET data	; Where the data comes from
	mov ATR_Ptr, ax		; Store for reading of attributes strings

	add ax, pack.argbk1	; Add in the length of the data
	mov ATR_End_ptr, ax	; Store the ending pointer

ATR_LP1:
	call ATR_Get_attribute	; Get the attribute
	 jc ATR_9		;  End of file

; Determine attribute type

	cmp ATR_Attribute, "!"	; Is the attribute the one for file size?
	 je ATR_Do_filesize	;  Yes, go handle it

ATR_Ignore:
	mov ax, ATR_Length	; Get the attr length
	add ATR_Ptr, ax		; Advance the pointer
	jmp ATR_LP1		; Go try for another attribute

; Type is "file size in K bytes"

ATR_Do_filesize:
	mov cx, ATR_Length	; Load up number of expected digits
	call ATR_Get_number	; Get the file size
	 jc ATR_9		;  EOF or non-numeric junk

	mov ATR_KBytes, ax	; Save file size in K bytes

	mov dx, ax		; Copy file size in K to dx
	mov cl, 6		; This many bits
	shr dx, cl		; Get high order 10 bits from ax into low
				;  order position in dx
	mov cl, 10		; This many bits
	shl ax, cl		; Get low order 6 bits from ax into high
				;  order position in ax
	mov bx, 100		; Get a 100 (base of percentage) into bx
	div bx			; Convert doubleword byte count into percent-
				;  adjusted value for PerPr routine
	mov OFilSz, ax		; Store it away for later

; Jump here after user has inserted a new disk

ATR_Try_again:

	call ATR_Get_disk_freespace ; See how much space is left on the disk
	mov ATR_Avail, ax	; Store the answer for possible later display
	cmp ax, ATR_KBytes	; Enough room for the file?
	 jae ATR_LP1		;  There is enough room, read any other
				;  attributes we find

	mov ah, ClosF		; Close the file
	mov dx, OFFSET Fcb
	int Dos

	mov ah, DelF		; Delete it
	int Dos

	call ATR_Show_space_problem ; Inform the user, ask for a new disk

	mov ah, ConInQ		; Quiet console input
	int Dos			; Wait until user hits a key

	cmp al, 3		; Control-C?
	 je ATR_Abort		;  Yes, don't accept the file

	call ATR_Make_new_file	; Create the file on the new disk (blow old
				;  file away if it already exists)

	call ATR_Fix_screen	; Get rid of the message

	jmp ATR_Try_again	; Go try again

ATR_9:	mov pack.numtry,0	; Reset the number of tries
	mov pack.argbk1,0	; No data.  (Packet number still in argblk.)
	sub cx, cx		; Make a zero
	cmp flags.cxzflg,0	; Interrupt file transfer? [20c]
	 je ATR_10		; Nope. [20c] 

	mov bx,offset data	; Send data in ACK in case remote... [20c] 
	mov ah,flags.cxzflg	; ... knows about ^X/^Z. [20c]
	mov [bx],ah		; Put data into the packet. [20c]
	mov pack.argbk1,1	; Set data size to 1. [20c]
	mov cx,1

; Successful receipt of an Attribute packet, ACK the packet

ATR_10: call doenc

	mov ah,'Y'		; Acknowledge packet
	call spack
	 jmp abort

	ret			; Done here

; Routines used to handle attribute packets

	PUBLIC ATR_Get_attribute, ATR_Exit_error, ATR_Exit, ATR_Abort
	PUBLIC ATR_Get_a_char, ATR_Get_number, ATR_Get_disk_freespace
	PUBLIC ATR_Show_space_problem

ATR_Get_attribute:
	call ATR_Get_a_char	; Get the attribute character
	 jc ATR_Exit		;  End of file

	mov ATR_Attribute, al	; Store it

	call ATR_Get_a_char	; Get the number of digits in the file size
	 jc ATR_Exit		;  End of file

	sub al, 32		; Convert to true number
	cbw			; Zero ah
	mov ATR_Length, ax	; Store the data length

; Make sure that this is a valid length

	mov ax, ATR_End_ptr	; Get ending ptr
	sub ax, ATR_Ptr		; Get length until end-of-data
	cmp ax, ATR_Length	; Is size sufficient for this data subfield?
	 jl ATR_Exit_error	;  No, bomb it

	clc			; No error
	ret			; Return

ATR_Exit_error:
	stc			; Force error flag

ATR_Exit:
	ret			; Return

ATR_Abort:
	mov dx,offset erms12
	call Show_error		; Display message
	mov bx,offset erms12a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort

ATR_Get_a_char:

;   Returns ... 
;	Carry set = No char to be found
;	al/ the character, if any

	push si			; Save reg
	mov si, ATR_Ptr		; Our reading ptr
	cmp si, ATR_End_ptr	; Pointing at end-of-data, or higher?
	 jb ATR_GCh_1		;  No, no error

	stc			; Flag the error
	jmp SHORT ATR_GCh_2	; Finish up

ATR_GCh_1:
	cld			; Forwards
	lodsb			; Pick up the new character
	mov ATR_Ptr, si		; Save updated ptr
	clc			; No error

ATR_GCh_2:
	pop si			; Restore reg
	ret			; Done here

ATR_Get_number:

;   Call with ...
;	cx/ number of digits to read
;
;   Returns ... 
;	Carry set = No number
;	ax/ the number, if any

	sub bx, bx		; Clear a working register

PN_1:	call ATR_Get_a_char	; Get a char
	 jc ATR_Badnum		;  None to be got

	cmp al, '0'		; Lower than 0?
	 jb ATR_Badnum		;  Yes, done here
	cmp al, '9'		; Higher than 9?
	 ja ATR_Badnum		;  Yes, done here

	sub al, '0'		; Make ASCII digit into decimal
	sub ah, ah		; Clear ah
	xchg ax, bx		; Swap ax and bx
	mov dx, 10		; Get a ten
	mul dx			; Multiply old number by ten
	add bx, ax		; Add in the new digit
	loop PN_1		; Go get another char, if more to do

	clc			; We have a number
	mov ax, bx		; Copy over the number
	ret			; Done here

ATR_Badnum:
	stc			; No number
	ret			; Go home

; See how much space is available on the connected disk, returns with ...
;	ax/ Number of Kilobytes (1024) available on "default" disk

ATR_Get_disk_freespace:
	
	sub dl, dl		; Want data for the default drive
	mov ah, 36h		; DOS function call for space available
	int DOS			; Do it .

	cmp ax, 0ffffh		; Invalid drive spec?
	 je ATR_DSK_Problem	;  There is some problem

;   At this point, we have the following ...
;		ax/ number of sectors per cluster
;		bx/ number of free clusters
;		cx/ number of bytes per sector

	mul cx			; ax * cx --> ax, number of bytes per cluster
	mov cl, 9		; Want to shift right this many bits
	shr ax, cl		; Divide by 512, so final result will fit in ax
	mul bx			; ax * bx --> ax, (number of bytes free)/512
	shr ax, 1		; Divide by 2 to convert this to Kilobytes
	ret			; Done here

ATR_DSK_Problem:
	sub ax, ax		; Pretend no disk space free
	ret			; Done here

ATR_Show_space_problem:

Tmsg	MACRO Message
	mov dx, OFFSET Message
	mov ah, PrStr
	int Dos
	ENDM

GoMsg	MACRO Number
	mov dx, SPC_Addr&Number
	call PosCur
	Tmsg SPC_Msg&Number
	ENDM

	GoMsg 1
	mov ax, ATR_KBytes
	call Nout
	Tmsg SPC_Msg2

	GoMsg 3
	mov ax, ATR_Avail
	call Nout
	Tmsg SPC_Msg4

	GoMsg 5
	GoMsg 7

	jmp Beep		; Go make a noise, ret from there

ATR_Make_new_file:

	mov ah, DelF		; Delete the file if it exists
	mov dx, OFFSET Fcb
	int Dos

	mov ah, MakeF		; Now create it
	int Dos

	ret

ATR_Fix_screen:

Clear_it MACRO Address
	mov dx, Address		;; Position
	call PosCur		;; Go there
	call ClearL		;; Clear out any existing message
	ENDM

	Clear_it SPC_Addr1	; Clear each line
	Clear_it SPC_Addr3
	Clear_it SPC_Addr5
	Clear_it SPC_Addr7

	ret

RAttr	ENDP

 
;	Receive data
 
RDATA	PROC

	cmp pack.numtry,maxtry	; Get the number of tries
	 jl rdata1

	mov dx,offset erms10
	call Show_error		; Display message
	mov bx,offset erms10a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort

rdata1: inc pack.numtry		; Save the updated number of tries
	call rpack		; Get a packet
	 jmp Nak0		;  Trashed packet: nak, retry

	cmp ah,'D'		; Is it a data packet?
	je rdat11

	call dodec		; Decode data
	jmp rdata2		;  No, try next type

rdat11: mov ax,pack.pktnum	; Get the present packet number
	cmp ax,pack.argblk	; Is the packet's number correct?
	jz rdat14

	cmp pack.oldtry,maxtry	; Have we reached the maximum number of tries?
	jl rdat12		; If not proceed

	mov dx,offset erms10
	call Show_error		; Display message
	mov bx,offset erms10a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort

rdat12: inc pack.oldtry		; Save the updated number of tries
	mov ax,pack.pktnum
	cmp ax,0		; Had we wrapped around? [18 start]
	jne rdatx

	mov ax,64

rdatx:	dec ax			; [14] [18 end -- new label]
	cmp ax,pack.argblk	; Is the packet's number one less than now?
	je rdat13

	jmp nak0		; No, NAK it and try again

rdat13: call updrtr		; Update retry count
	mov pack.numtry,0	; Reset number of tries
	mov pack.argbk1,0	; No data.  (The packet number is in argblk.)
	mov cx,0
	call doenc
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp Abort

	ret

rdat14: inc ax			; Increment the packet number
	and ax,3FH		; Turn off the two high order bits
	mov pack.pktnum,ax	; Save modulo 64 of the number
	inc pack.numpkt		; Increment the number of packets
	mov ah,pack.numtry	; Get the number of tries
	mov pack.oldtry,ah	; Save it
	mov ax,pack.argbk1	; Get the length of the data
	cmp flags.cxzflg,0	; Has the user typed a ^X or ^Z? [20c]
	je rdt14x		; No, write out the data

	cmp flags.abfflg,1	; Discard incomplete files?
	je rdat15		; If yes don't write data out to file. [20c]

rdt14x:	mov bx,offset data	; Where the data is. [25]
	call ptchr
	 jmp Abort		;  Unable to write out chars

rdat15: mov pack.numtry,0	; Reset the number of tries
	mov pack.argbk1,0	; No data.  (Packet number still in argblk.)
	mov cx,0
	cmp flags.cxzflg,0	; Interrupt file transfer? [20c]
	je rdat16		; Nope. [20c] 

	mov bx,offset data	; Send data in ACK in case remote... [20c] 
	mov ah,flags.cxzflg	; ... knows about ^X/^Z. [20c]
	mov [bx],ah		; Put data into the packet. [20c]
	mov pack.argbk1,1	; Set data size to 1. [20c]
	mov cx,1

rdat16: call doenc
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp Abort

	ret

rdata2: cmp ah,'F'		; Start of file?
	je rdat20		; Yup. [21c]

	cmp ah,'X'		; Text header packet? [21c]
	jne rdata3		;  No, try next type

rdat20: cmp pack.oldtry,maxtry	; Reached the max number of tries? [21c]
	jl rdat21		; If not proceed

	mov dx,offset ermes8
	call Show_error		; Display message
	mov bx,offset ermes8a
	call errpack		; Send error packet just in case
	jmp abort		; Change the state to abort

rdat21: inc pack.oldtry		; Save the updated number of tries
	mov ax,pack.pktnum
	cmp ax,0		; Had we wrapped around? [18 start]
	jne rdaty

	mov ax,64

rdaty:	dec ax			; [14 Omitted accidentally - D.T.] [18 end]
	cmp ax,pack.argblk	; Is the packet's number one less than now?
	je rdat22

	jmp nak0		; No, NAK it and try again

rdat22: call updrtr		; Update retry count
	mov pack.numtry,0	; Reset number of tries
	mov pack.argbk1,0	; No data.  (The packet number is in argblk.)
	mov cx,0
	call doenc
	mov ah,'Y'		; Acknowledge packet

	call spack		; Send the packet
	 jmp Abort

	ret

rdata3: cmp ah,'Z'		; Is it a EOF packet?
	je rdat3x		; [13]

	jmp rdata4		; Try and see if its an error. [13]

rdat3x: mov ax,pack.pktnum	; Get the present packet number. [13]
	cmp ax,pack.argblk	; Is the packet's number correct?
	je rdat32

	jmp nak0		; No, NAK it and try again

rdat32: inc ax			; Increment the packet number
	and ax,3FH		; Turn off the two high order bits
	mov pack.pktnum,ax	; Save modulo 64 of the number
	inc pack.numpkt
	cmp flags.cxzflg,0	; Do we want to discard the file? [20c]
	jne rdt32x		; Yes. [20c]

	cmp pack.argbk1,1	; One piece of data? [20c]
	jne rdat33		; Nope - finish writing out file? [20c]

	mov bx,offset data	; Get data area. [20c]
	mov ah,[bx]		; Get the data. [20c]
	cmp ah,'D'		; "D" for discard? [20c]
	jne rdat33		; Nope - write out file. [20c]

rdt32x:	cmp flags.abfflg,0	; Keep incomplete files?
	je rdat33		; Yes, go write it out

    PUBLIC MSRECV_close_file_1

MSRECV_close_file_1:
	mov ah,closf		; First, close the file
	mov dx,offset fcb	; Give the file parameters. [20c]
	int dos			; Kill it, ignore errors. [20c]

	mov ah,delf		; Delete the file if opened. [20c]
	int dos

	cmp flags.cxzflg,'X'	; Kill one file or all? [20c]
	jne rdat36		; No so leave flag alone. [20c]

	call cxmsg		; Clear msg about interrupt. [20c]
	mov flags.cxzflg,0	; Reset - ^X only kills one file. [20c]
	jmp rdat36

	PUBLIC rdat33

rdat33: mov bx,bufpnt		; Get the dma pointer
	mov ax,80H
	sub ax,chrcnt		; Get the number of chars left in the DMA
	cmp flags.eofcz,0	; should we write a ^Z?
	jz rdat35		; no, keep going

	cmp flags.xflg,0	; writing to a file?
	jne rdat35		; no, skip ^Z

	cmp ax,80H		;   [13 start]
	jne rdat34

	call outbuf		; Write out buffer if no room for ^Z
	 jmp abort

	mov ax,0		;   [13 end]
	inc chrcnt		; Increment size by one (not two). [21b]

rdat34: mov cl,'Z'-100O		; Put in a ^Z for EOF
	mov [bx],cl		; Add it. [21c]
	inc ax
	dec chrcnt

rdat35:	mov cx,chrcnt
	mov temp,cx
	call outbuf		; Output the last buffer
	 jmp abort		; Give up if the disk is full
	mov ax,temp		; Prepare for the function call
	call fixfcb

	cmp Flags.XFlg, 0	; Writing to screen?
	 je MSRECV_close_file_2	;  No, go close the file

	mov ah, PrStr		; Code to write to screen
	mov dx, OFFSET CrLf	; A CrLf
	int Dos			; Type it

	mov ah, PrStr		; Code to write to screen
	mov dx, OFFSET CrLf	; A CrLf
	int Dos			; Type another CrLf

	jmp SHORT rdat37	; Skip over this code

    PUBLIC MSRECV_close_file_2

MSRECV_close_file_2:
	mov ah,closf		; Close up the file
	mov dx,offset fcb
	int dos

rdat36:	cmp flags.destflg,1	; Writing to disk?
	je rdat37		; Yes, skip next part
	cmp flags.xflg,1	; Writing to screen?
	je rdat37		; Yes, skip this part
	mov dl,ff		; Send a form feed
	mov ah,lstout		; Write out to first printer
	int dos

rdat37:	mov ah,pack.numtry	; Get the number of tries
	mov pack.oldtry,ah	; Save it
	mov pack.numtry,0	; Reset the number of tries
	mov pack.argbk1,0	; No data.  (The packet number is in argblk.)
	mov cx,0
	call doenc
	mov ah,'Y'		; Acknowledge packet
	call spack		; Send the packet
	 jmp abort
	mov pack.state,'F'
	ret
rdata4: cmp ah,'E'			; Is it an error packet
	jne rdata5
	call error
rdata5: jmp abort
RDATA	ENDP

 
ABORT   PROC

	mov pack.state,'A'      ; Otherwise abort
	ret

ABORT   ENDP


; Jumping to this location is like retskp.  It assumes the instruction
;   after the call is a jmp addr
 
RSKP    PROC    NEAR
	pop bp
	add bp,3
	push bp
;	ret
RSKP    ENDP

R	PROC	NEAR
	ret
R	ENDP

code	ends 
	END

