home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
cpm86
/
c86pro.a86
< prev
next >
Wrap
Text File
|
2011-08-09
|
43KB
|
1,443 lines
; C86PRO.A86
; * * * * * * * * * * * * * * * * version 3.0 * * ** * * * * * * * * * * * *
; Allows packet echo - CGL
; * * * * * * * * * * * * * * * version 2.9 * * * * * * * * * * * * * * *
; [34c] Add sorted wildcard SENDs with initial filename
; * * * * * * * * * * * * * * * version 2.7 * * * * * * * * * * * * * * *
; [31] Fix display on file renaming.
; RonB, 05/05/84
; [30c] Isolate ANSI escape sequences for machine independence.
; [29g] Add 8th bit quoting.
; [29d] Enlarge receive buffer and check for packet overruns.
; [29b] Add TAKE processing (close command file when aborting).
; [29a] Send error packet when aborting.
; RonB, 04/08/84
; * * * * * * * * * * * * * * * version 2.6 * * * * * * * * * * * * * * *
; [28b] Make file-not-found error more informative (include filename).
; [28a] Clear attribute bits from filename before sending
; RonB, 03/27/84
; [25] - make KERCMD more modular by eliminating some use of text
; strings by other modules (KERPRO, KERSYS), and moving some
; parsing into KERCMD (ESCAPE and EOLSET logic in KERSYS)
; * * * * * * * * * * * * * * * version 2.4 * * * * * * * * * * * * * * *
; [21a] Add timeout enable/disable
; RonB,03/05/84
; [20a] Fix version & send/receive header
; [20e] Clean up environment better before rebooting in KABORT
; RonB,03/02/84
; [19f] Add ^X/^Z file interruption - adapted from PC Kermit V1.20
; Put in Help line for above.
; [19g] Put in timeouts.
; R. Garland 2/84
; * * * * * * * * * * * * * * * version 2.1 * * * * * * * * * * * * * * *
; [14] Fix nout to print decimal.
; RonB,12/28/83
; [13] Use control-Z's for filler in partial sectors instead of nulls.
; RonB,12/27/83
; [12] Allow user abort from the keyboard in the send and receive routines.
; RonB,12/27/83
; [9] Fix filename parsing, and add wildcard ability.
; RonB,12/26/83
; * * * * * * * * * * * * * * * version 2.0 * * * * * * * * * * * * * * *
; This module contains the routines that actually implement the Kermit
; protocol.
; Packet definitions.
maxpkt equ '~'-' '+2O ;Maximum size of a packet.
maxtry equ 05O ;Default number of retries on a packet.
imxtry equ 20O ;Default number of retries send initiate.
drpsiz equ 5EH ;Default receive packet size.
dspsiz equ 20H ;Default send packet size.
dstime equ 0AH ;Default send time out interval.
drtime equ 05H ;Default receive time out interval.
dspad equ 00H ;Default send padding.
drpad equ 00H ;Default receive padding.
dspadc equ 00H ;Default send padding char.
drpadc equ 00H ;Default receive padding char.
dseol equ cr ;Default send EOL char.
dreol equ cr ;Default receive EOL char.
dsquot equ '#' ;Default send quote char.
drquot equ '#' ;Default receive quote char.
dqbin equ '&' ;Default 8th-bit quote char. ;[29g]
bufsiz equ 80H ;Size of DMA.
; A few control characters
ctlc equ 03H ;[19f]
ctlx equ 18H ;[19f]
ctlz equ 1AH ;[19f]
DSEG $
; Program storage.
belflg db 1 ;Use bell.
incmod db 0 ;Insert Character mode.
hierr db 0 ;Non-ascii char (non-zero if yes).
parflg db defpar ;Parity flag (default none.)
flwflg db 0 ;File warning flag (default off).
ibmflg db 0 ;IBM flag (default off).
vmeflg db 0 ;VME flag (default off);
incnt dw 0 ;Number of chars read in from port.
pktptr dw 0 ;Position in receive packet.
spsiz db dspsiz ;Send packet size.
rpsiz db drpsiz ;Receive packet size.
stime db dstime ;Send time out.
rtime db drtime ;Receive time out.
spad db dspad ;Send padding.
rpad db drpad ;Receive padding.
spadch db dspadc ;Send padding char.
rpadch db drpadc ;Receive padding char.
seol db dseol ;Send EOL char.
reol db dreol ;Receive EOL char.
squote db dsquot ;Send quote char.
rquote db drquot ;Receive quote char.
ebquot db 'Y' ;Send 8th-bit quote char. ;[29g]
pktnum dw 0 ;Packet number.
numpkt dw 0 ;Total number of packets sent.
numrtr dw 0 ;Total number of retries.
numtry db 0 ;Number of tries on this packet.
oldtry db 0 ;Number of tries on previous packet.
cxzflg db 0 ;[19f] flag for ^X/^Z file interruption
state db 0 ;Present state of the automaton.
packet rb 4 ;Packet (data is part of it).
data rb 60H ;Data and checksum field of packet. ;[29d]
recpkt rb 100H ;Receive packet storage. ;[29d]
temp dw 0
argblk dw 0 ;For subroutine arguments.
argbk1 dw 0
argbk2 dw 0
argbk3 dw 0
tickst dw 10*(7470/clckrt);[19g] "magic" formula for loops/tick
;[19g] CLCKRT is the system clock rate ...
;[19g] ... defined in KERIO
ticklp dw 0 ;[19g] Dynamic loop count for tick
tickct db dstime ;[19g] # ticks for timeout to occur
tmodon db 0 ;[19g] flag for time-out message
CSEG $
; Check for a user abort or interrupt during the send or receive ;[12] begin
; modified by Rg.
kabort:
call dbinst ;Check if a char has been typed.
jmp r ;[19f] Merrily return.
call dbin ;Get the character.
cmp al, ctlc ;Abort if control-C [19f]
je kabrt2
cmp al, ctlx ;[19f] Is it control-x ?
je kabrta ;[19f] yes
cmp al, ctlz ;[19f] control-z ?
jne kabrtb ;[19f] no
kabrta: add al, 100O ;[19f] make into 'X' or 'Z'
mov cxzflg, al ;[19f] set the flag
call intmsg ;[19f] reassure the user
ret ;[19f] return
kabrtb: cmp al, cr ;if <cr> do a timeout ;[29a] begin
jne kabrtc
pop bx ;return of kabort
pop bx ;receive packet pointer
;... next is return of inpkt
ret ;return to timeout routine ;[29a] end
kabrtc: cmp al, escchr ;or the escape character followed by 'C'.
jne kabrt9
mov cx, 1000 ;Only wait just so long for the next char.
kabrt1: push cx
call dbin
pop cx
cmp al, 0
loope kabrt1
cmp al, ctlc ;Control-C also works here. [19f]
je kabrt2
and al, 137O ;Capitalize it.
cmp al, 'C' ;If not a 'C' then continue.
jne kabrt9
kabrt2: cmp tkflg, 0 ;Close any command file in use ;[29b] begin
je kabrt3
call tkcls ;[29b] end
kabrt3: call binst ;Clear out extraneous input ;[29a] begin
jmp kabrt4 ;If none, go abort this transmission.
call bin
jmps kabrt2
kabrt4: pop bx ;return from kabort
pop bx ;receive packet pointer
pop bx ;return from inpkt
pop bx ;return from rpack
;... next is return from r??? to read
mov dx, offset erms21 ;Print '* aborted *' message.
jmp fatal ;[29a] end
kabrt9: mov dl, bell ;beep [19f]
call dbout ; [19f]
ret ;return no error [19f]
; Send the generic finish command to the remote Kermit.
finsen: mov ah, 'F' ;Ask for the finish command.
call gensen
ret
; Send the generic logout command to the remote Kermit.
byesen: mov ah, 'L' ;Ask for the logout command.
call gensen
ret
; This procedure processes all the generic single packet sends.
gensen: mov temp, ax ;Save the specific generic command.
mov numtry, 0 ;Initialize count.
call cfibf ;Clear out input buffer of extra NAKs.
fins1: mov ah, numtry
cmp ah, maxtry ;Too many times?
js fins3 ;Nope, try it.
fins2: mov dx, offset erms18
call tcrmsg
ret
fins3: inc numtry ;Increment number of tries.
mov argblk, 0 ;Packet number zero.
mov argbk1, 1 ;One piece of data.
mov bx, offset data
mov ax, temp ;Get the generic command.
mov [bx], ah ;Finish running Kermit.
mov ah, 'G' ;Generic command packet.
call spack
jmp fins2 ;Tell user and die.
call rpack ;Get ACK.
jmp fins1 ;Go try again.
cmp ah, 'Y' ;Got an ACK?
jnz fins4
ret ;Yes, then we're done.
fins4: cmp ah, 'E' ;Error packet?
jnz fins1 ;Try sending it again.
call error1
ret
; Packet routines
; Send_Packet
; This routine assembles a packet from the arguments given and sends it
; to the host.
;
; Expects the following:
; AH - Type of packet (D,Y,N,S,R,E,F,Z,T)
; ARGBLK - Packet sequence number
; ARGBK1 - Number of data characters
;
; Returns: +1 always
spack: push ax ;Save the packet type.
mov bx, offset packet ;Get address of the send packet.
mov ah, soh ;Get the start of header char.
mov [bx], ah ;Put in the packet.
inc bx ;Point to next char.
mov ax, argbk1 ;Get the number of data chars.
xchg ah, al
add ah, ' '+3 ;Real packet character count made printable.
mov [bx], ah ;Put in the packet.
inc bx ;Point to next char.
mov cl, ah ;Start the checksum.
mov ax, argblk ;Get the packet number.
xchg ah, al
add ah, ' ' ;Add a space so the number is printable.
mov [bx], ah ;Put in the packet.
inc bx ;Point to next char.
add cl, ah ;Add the packet number to the checksum.
pop ax ;Get the packet type.
mov [bx], ah ;Put in the packet.
inc bx ;Point to next char.
add cl, ah ;Add the type to the checksum.
mov dx, argbk1 ;Get the packet size.
spack2: cmp dx, 0 ;Are there any chars of data?
jz spack3 ; No, finish up.
dec dx ;Decrement the char count.
mov ah, [bx] ;Get the next char.
inc bx ;Point to next char.
add cl, ah ;Add the char to the checksum.
jmp spack2 ;Go try again.
spack3:
sp3x: mov ah, cl ;Get the character total.
mov ch, cl ;Save here too (need 'cl' for shift).
and ah, 0C0H ;Turn off all but the two high order bits.
mov cl, 6
shr ah, cl ;Shift them into the low order position.
mov cl, ch
add ah, cl ;Add it to the old bits.
and ah, 3FH ;Turn off the two high order bits. (MOD 64)
add ah, ' ' ;Add a space so the number is printable.
mov [bx], ah ;Put in the packet.
inc bx ;Point to next char.
mov ah, seol ;Get the EOL the other host wants.
mov [bx], ah ;Put in the packet.
inc bx ;Point to next char.
mov ah, 0 ;Get a null.
mov [bx], ah ;Put in the packet.
cmp debug, 0 ;debug mode.
je spack4
inc bx
mov ah, '$'
mov [bx], ah
mov dx, offset scrsp ;Print string to move cursor.
call poscur ;[30c] begin
call clreol ;Clear current line
mov dl, lf ; and next one
call bout
call clreol
mov dx, offset scrsp ;Print string to move cursor.
call poscur ;[30c] end
mov dx, offset spmes
call tmsg
mov dx, offset packet
call tmsg ;Debug end.
spack4: call outpkt ;Call the system dependent routine.
jmp rskp
; Write out a packet.
outpkt: mov dh, spad ;Get the number of padding chars.
outpk2: dec dh
cmp dh, 0
jl outpk3 ;If none left proceed.
mov al, spadch ;Get the padding char.
call prtout ;Output it.
jmp outpk2
outpk3: mov bx, offset packet ;Point to the packet.
outlup: mov al, [bx] ;Get the next character.
cmp al, 0 ;Is it a null?
jnz outlp2
ret
outlp2: call prtout ;Output the character.
inc bx ;Increment the char pointer.
jmp outlup
; Receive_Packet
; This routine waits for a packet arrive from the host.
rpack: call inpkt ;Read up to a carriage return.
jmp rptimo ; User timed us out.
rpack0: call getchr ;Get a character.
jmp rpack ; Hit the carriage return, go try again.
cmp ah, soh ;Is the char the start of header char?
jne rpack0 ; No, go until it is.
rpack1: call getchr ;Get a character.
jmp r ; Hit the carriage return, return bad.
cmp ah, soh ;Is the char the start of header char?
jz rpack1 ; Yes, then go start over.
mov cl, ah ;Start the checksum.
sub ah, ' '+3 ;Get the real data count.
mov dh, ah ;Save it for later.
mov al, ah ;Swap halves.
mov ah, 0
mov argbk1, ax ;Save the data count.
call getchr ;Get a character.
jmp r ; Hit the carriage return, return bad.
cmp ah, soh ;Is the char the start of header char?
jz rpack1 ; Yes, then go start over.
add cl, ah ;Add it to the checksum.
sub ah, ' ' ;Get the real packet number.
mov al, ah ;Swap halves.
mov ah, 0
mov argblk, ax ;Save the packet number.
call getchr ;Get a character.
jmp r ; Hit the carriage return, return bad.
cmp ah, soh ;Is the char the start of header char?
jz rpack1 ; Yes, then go start over.
mov temp, ax ;Save the message type.
; CGL mod for VME packet echo
cmp ah, packet + 3 ; compare with the type of this received one
je rpack ; if the same go back and get next
; end of CGL mod
add cl, ah ;Add it to the checksum.
mov bx, offset data ;Point to the data buffer.
rpack2: dec dh ;Any data characters?
js rpack3 ; If not go get the checksum.
call getchr ;Get a character.
jmp r ; Hit the carriage return, return bad.
cmp ah, soh ;Is the char the start of header char?
jz rpack1 ; Yes, then go start over.
mov [bx], ah ;Put the char into the packet.
inc bx ;Point to the next character.
add cl, ah ;Add it to the checksum.
jmp rpack2 ;Go get another.
rpack3: call getchr ;Get a character.
jmp r ; Hit the carriage return, return bad.
cmp ah, soh ;Is the char the start of header char?
jz rpack1 ; Yes, then go start over.
sub ah, ' ' ;Turn the char back into a number.
mov dh, cl ;Get the character total.
and dh, 0C0H ;Turn off all but the two high order bits.
mov ch, cl
mov cl, 6
shr dh, cl ;Shift them into the low order position.
mov cl, ch
add dh, cl ;Add it to the old bits.
and dh, 3FH ;Turn off the two high order bits. (MOD 64)
cmp dh, ah ;Are they equal?
jz rpack4 ; If so finish up.
call cfibf ;Clear out any other characters on the line.
ret ;And return failure.
rpack4: mov ah, 0
mov [bx], ah ;Put a null at the end of the data.
mov ax, temp ;Get the type.
call cfibf ;Clear out any other characters on the line.
jmp rskp
rptimo: call cfibf ;On a time out clear out any remaining chars.
ret
inpkt: mov bx, offset recpkt ;Point to the beginning of the packet.
mov incnt, 0
inpkt2: mov al, stime ;[19g] set up timeout loop.
mov tickct, al ;[19g]
mov ax, tickst ;[19g] "magic" number loops/tick
mov ticklp, ax ;[19g]
inpkta: cmp tmrflg, 0 ;Is timeout disabled? ;[21a]
je inpktb ; If so, skip tick routine ;[21a]
dec ticklp ;[19g]
cmp ticklp, 0 ;[19g] done this tick?
jne inpktb ;[19g] not yet
mov ax, tickst ;[19g] reload loop count
mov ticklp, ax ;[19g]
call ticmsg ;[19g] beep for debugging
dec tickct ;[19g]
cmp tickct, 0 ;[19g] timed-out?
jne inpktb ;[19g] not yet
call tmomsg ;[19g] alert user
jmp inpkt9 ;[19g] go time-out
inpktb: push bx ;[19g][12] bx gets trashed by kb status check.
call kabort ;[19g] Doesn't return if user aborted.
pop bx ;[19g]
call instat ;Any char there?
jmp inpkta ; Go until there is one.
call inchr ;Get the character.
mov [bx], al ;Put the char in the packet.
inc bx
inc incnt
cmp incnt, length recpkt ;Have we overrun the input buffer? ;[29d]
jb inpktc
jmp inpkt ;If so, just clear and restart
inpktc: cmp al, reol ;Is it the EOL char? ;[29d] end
jne inpkt2 ;If not loop for another.
cmp incnt, 1 ;Ignore bare CR.
jne inpkt6
jmp inpkt
inpkt6: cmp ibmflg, 0 ;Is this the (dumb) IBM mainframe?
jz inpkt4 ;If not then proceed.
inpkt5: cmp state, 'S' ;Check if this is the Send-Init packet.
jz inpkt4 ;If so don't wait for the XON.
inpkt3: call instat ;Wait for the turn around char.
jmp inpkt3
call inchr
cmp al, xon ;Is it the IBM turn around character?
jne inpkt3 ;If not, go until it is.
inpkt4: cmp debug, 0
jz inpkt7 ;If not debugging don't print the packet.
mov al, '$' ;Get a dollar sign.
mov [bx], al ;Put in the packet.
inc bx ;Point to next char.
mov dx, offset scrrp ;Print the packet.
call poscur ;[30c] begin
call clreol ;Clear current line
mov dl, lf ; and next one
call bout
call clreol
mov dx, offset scrrp ;Print string to move cursor.
call poscur ;[30c] end
mov dx, offset rpmes
call tmsg
mov dx, offset recpkt
call tmsg
inpkt7: mov bx, offset recpkt
mov pktptr, bx ;Save the packet pointer.
call tmoclr ;[19g] Clear timeout message
jmp rskp ;If so we are done.
inpkt9: ret ;return failure on time out.
getchr: push bx
mov bx, pktptr ;Get the packet pointer.
mov ah, [bx] ;Get the char.
inc bx
mov pktptr, bx
pop bx ;Restore BX.
cmp ah, reol ;Is it the EOL char?
jne getcr2 ;If not return retskp.
ret ;If so return failure.
getcr2: jmp rskp
;This is where we go if we get an error packet. A call to ERROR
; positions the cursor and prints the message. A call to ERROR1
; just prints a CRLF and then the message.
error: mov state, 'A' ;Set the state to abort.
mov dx, offset screrr
call poscur ;[30c]
jmp error2
error1: call tcrlf
error2: mov bx, offset data ;Get to the string.
add bx, argbk1 ;Add the length of the data.
mov ah, '$' ;Put a dollar sign at the end.
mov [bx], ah
mov dx, offset data ;Print the error message.
call tmsg
ret
; Jump here if we die during a transfer. Print the error message in
; DX and abort.
fatal: push dx ;Save the error message.
mov dx, offset screrr
call poscur ;[30c]
pop dx
call tmsg
jmp abort ;Change the state to abort.
; Print the status message in DX, ring the bell and position of the prompt.
fnstat: push dx
mov dx, offset scrst ;Print string to move cursor.
call poscur ;[30c]
pop dx
call tmsg
mov dx, offset ender ;Ring them bells.
call tmsg
mov dx, offset scrhlp ;[19f] Cursor position
call poscur ;[30c]
call clreol ;[19f] Clear help line ;[30c]
mov dx, offset scrrpr ;Put cursor back
call poscur ;[30c]
ret
; This routine sets up the data for init packet (either the
; Send_init or ACK packet).
rpar: mov ah, rpsiz ;Get the receive packet size.
add ah, ' ' ;Add a space to make it printable.
mov [bx], ah ;Put it in the packet.
mov ah, rtime ;Get the receive packet time out.
add ah, ' ' ;Add a space.
mov 1[bx], ah ;Put it in the packet.
mov ah, rpad ;Get the number of padding chars.
add ah, ' '
mov 2[bx], ah ;Put it in the packet.
mov ah, rpadch ;Get the padding char.
add ah, 100O ;Uncontrol it.
and ah, 7FH
mov 3[bx], ah ;Put it in the packet.
mov ah, reol ;Get the EOL char.
add ah, ' '
mov 4[bx], ah ;Put it in the packet.
mov ah, rquote ;Get the quote char.
mov 5[bx], ah ;Put it in the packet.
mov ah, ebquot ;Get 8th-bit quote char ;[29g] begin
mov 6[bx], ah ;Put it in the packet.
mov ah, '1' ;Set single character check type
mov 7[bx], ah ;Put it in the packet.
mov ah, ' ' ;Set no repeat prefix
mov 8[bx], ah ;Put it in the packet.
mov ah, 0 ;Initialize capability byte
cmp tmrflg, 0 ;Are we able to time out?
je rpar1 ; No, leave bit set to zero
or ah, 20h ; Otherwise set timeout capability flag
rpar1: add ah, ' ' ;Add space to make it printable
mov 9[bx], ah ;Put it in the packet.
mov ah, 10 ;Ten pieces of data. ;[29g] end
ret
; This routine reads in all the send_init packet information.
spar: push cx ;Save CX.
mov cx, ax ;Save the number of arguments.
mov ah, [bx] ;Get the max packet size.
sub ah, ' ' ;Subtract a space.
mov spsiz, ah ;Save it.
mov ax, cx ;[19g]
cmp al, 2 ;[19g] Fewer than two pieces?
jge spar1 ;[19g] ;[29g]
jmp sparx1 ;[29g]
spar1: mov ah, 1[bx] ;[19g] Get the timeout value
sub ah, ' ' ;[19g]
mov stime, ah ;[19g] save it.
mov ax, cx
cmp al, 3 ;Fewer than three pieces?
jge spar2 ;[29g]
jmp sparx2 ;[29g]
spar2: mov ah, 2[bx] ;Get the number of padding chars.
sub ah, ' '
mov spad, ah
mov ax, cx
cmp al, 4 ;Fewer than four pieces?
jge spar3 ;[29g]
jmp sparx3 ;[29g]
spar3: mov ah, 3[bx] ;Get the padding char.
add ah, 100O ;Re-controlify it.
and ah, 7FH
mov spadch, ah
mov ax, cx
cmp al, 5 ;Fewer than five pieces?
jge spar4 ;[29g]
jmp sparx4 ;[29g]
spar4: mov ah, 4[bx] ;Get the EOL char.
sub ah, ' '
mov seol, ah
mov ax, cx
cmp al, 6 ;Fewer than six pieces?
jge spar5 ;[29g]
jmp sparx5 ;[29g]
spar5: mov ah, 5[bx] ;Get the quote char.
mov squote, ah
mov ax, cx ;[29g] begin
cmp al, 7 ;Fewer than seven pieces?
jge spar6
jmp sparx6
spar6: mov ah, 6[bx] ;Get the 8th-bit quote char.
call doquo ;Set the quote character.
jmp sparxx
sparx1: mov stime, dstime ;Default timeout interval
sparx2: mov spad, dspad ;Default number of padding chars
sparx3: mov spadch, dspadc ;Default pad character
sparx4: mov seol, dseol ;Default eol character
sparx5: mov squote, dsquot ;Default send quote character.
sparx6: mov ebquot, 'N' ;No 8th bit quoting.
sparxx: pop cx ;[29g] end
ret ;If so we are done.
; Set 8-bit quote character based on my capabilities ;[29g] begin
; and the other Kermit's request.
doquo: cmp ebquot,'N' ;Can I do 8-bit quoting at all?
je dq2 ;No - so forget it.
cmp ebquot,'Y' ;Can I do it if requested?
jne dq0 ;No - it's a must that I do it.
mov ebquot,ah ;Do whatever he wants.
jmp dq2
dq0: cmp ah,'Y' ;I need quoting - can he do it?
je dq2 ;Yes - then all is settled.
cmp ah,'N' ;No - then don't quote.
je dq1
cmp ah,ebquot ;Both need quoting - chars must match.
je dq2
mov ah,'N'
dq1: mov ebquot,ah
dq2: mov ah,ebquot
cmp ah,rquote ;Same prefix?
je dq3 ;Not allowed, so don't do quoting.
cmp ah,squote ;Same prefix here?
je dq3 ;This is illegal too.
ret
dq3: mov ebquot,'N' ;Quoting will not be done.
ret ;[29g] end
; These are some utility routines.
; Increment the packet number.
incpkt: inc ax ;Increment it.
and ax, 3FH ;Turn off the two high order bits.
mov pktnum, ax ;Save modulo 64 of the number.
inc numpkt ;Increment the number of packets.
ret
; Check if the packet number is the present packet.
chkpeq: mov ax, argblk ;Get the packet number.
cmp ax, pktnum ;Is it the right packet number?
je chkpe2
ret ;No.
chkpe2: jmp rskp ;Yes.
; Is the packet number one more than present.
chkpom: mov ax, pktnum ;Get the present packet number.
inc ax ;Increment.
and ax, 03FH ;Account for wraparound.
cmp ax, argblk ;Is the packet's number one more than now?
jz chkpm2 ;Yes, success.
ret
chkpm2: jmp rskp
; Check if the packet number is the previous packet.
chkpol: inc oldtry ;Save the updated number of tries.
mov ax, pktnum ;Get the present packet number.
cmp ax, 0 ;Had we wrapped around?
jne chkpl2
mov ax, 64
chkpl2: dec ax ;Decrement.
cmp ax, argblk ;Is the packet's number one less than now?
je chkpl3
jmp rskp
chkpl3: ret
; Abort
abort: mov argblk, 0 ;packet number 0 ;[29a] begin
mov argbk1, 0 ;no data
mov ah, 'E' ;error type
call spack
jmp $ ;[29a] end
mov state, 'A' ;Otherwise abort.
ret
; ACK the packet.
uupack: call updat ;[19f] entry which doesn't zero argbk1
jmp ack1 ;[19f]
upack: call updat ;Update the number of tries.
ack: mov argbk1, 0 ;No data. (Packet number already in argblk).
ack1: mov ah, 'Y' ;Acknowledge packet.
call spack ;Send the packet.
jmp r
jmp rskp
updat: mov ah, numtry ;Get the number of tries.
mov oldtry, ah ;Save it.
mov numtry, 0 ;Reset the number of tries.
ret
; Re-ACK the previous packet.
reack: call nretry ;Increment and print the number of retries.
mov numtry, 0 ;Reset the number of tries.
mov ah, 'Y' ;Acknowledge packet.
call spack ;Send the packet.
jmp r
jmp rskp
; NAK that packet.
nak: mov ax, pktnum ;Get the packet number we're waiting for.
mov argblk, ax
mov argbk1, 0
mov ah, 'N' ;NAK that packet.
call spack
jmp abort
call nretry ;Increment and print the number of retries.
ret ;Go around again.
; Print the number of retries.
nretry: inc numrtr ;Increment the number of retries.
pretry: mov dx, offset scrnrt
call poscur ;[30c]
mov ax, numrtr
call nout ;Write the number of retries.
ret
; Print the number of packets.
pnmpkt: mov dx, offset scrnp ;Print string to move cursor.
call poscur ;[30c]
mov ax, numpkt
call nout ;Write the number of packets.
ret
; This routine prints the number in AX on the screen.
nout: push ax ;save all registers ;[14] begin
push bx
push cx
push dx
mov cx, 0 ;number of digits to print
mov bx, 10 ;radix to use for dividing
nout1: mov dx, 0 ;clear high word of dividend
div bx ;divide dx:ax by 10
push dx ;push this remainder
inc cx ;count it
cmp ax, 0 ;anything left in the quotient?
jne nout1 ; if so, keep dividing
nout2: pop dx ;get a digit
add dl, '0' ;make it ascii
push cx ;save our count
call bout ;print the digit
pop cx ;repeat until all digits printed
loop nout2
pop dx ;restore all registers
pop cx
pop bx
pop ax
ret
; Initialize file buffers and paint screen.
init:
call dspver ;Clear screen and display version header
mov dx, offset scrnp ;Position to packet location
call poscur
mov dx, offset pktlin ;[20a]
call tmsg
mov dx, offset scrhlp ;[19f] Cursor position
call poscur ;[19f] for help line ;[30c]
call revon ;Bottom line reverse ;[30c]
mov dx, offset infm10 ;[19f] Help for file transfer
call tmsg ;[19f]
call revoff ;[30c]
init1: mov chrcnt, bufsiz ;Number of chars left.
mov bufpnt, offset dma ;Addr for beginning.
ret
; Clear out the old filename on the screen.
clrfln: mov dx, offset scrfr ;Move cursor to file rename. ;[31] begin
call poscur
call clreol ;Clear to EOL. ;[31] end
mov dx, offset scrfln ;Move cursor to file name position.
call poscur ;[30c]
call clreol ;Clear to EOL. ;[30c]
ret
; acknowledge ^X/^Z with a message [19f] start
intmsg: mov dx, offset scrint ;position info
call poscur ;output it ;[30c]
mov dx, offset infms8 ;File message
cmp cxzflg, 'X' ;but first check
je intm01 ;yes it was X
mov dx, offset infms9 ;no it was 'Z' - file group.
cmp cxzflg, 'Z' ;or was it?
je intm01 ;yes - go output
call clreol ;anything else - clear line ;[30c]
jmps intm02 ;[30c]
intm01: call tmsg ;output it
intm02: ret ;goodbye [19f] end
; let the time-out clock "tick" ;[19g] start
ticmsg: mov dl, bell ;output a ...
call dbout ;... beep!
ret
; notify of time-out
tmomsg: mov dx, offset scrst ;cursor position
call poscur ;[30c]
mov dx, offset timoms ;timeout message
call tmsg
mov tmodon, 1 ;flag for message
ret
; clear time-out message
tmoclr: cmp tmodon, 0 ;message on screen?
jne tmocl1 ;yes - go get it
ret ;nothing to clear - return
tmocl1: mov dx, offset scrst ;cursor position
call poscur ;[30c]
call clreol ;clear line ;[30c]
mov tmodon, 0 ;indicate line is clear
ret ;[19g] end
; RECEIVE command
read: call init ;Paint the screen and initialize file buffers.
call cfibf ;Clear out any stacked NAKs.
read1: mov numpkt, 0 ;Set the number of packets to zero.
mov numrtr, 0 ;Set the number of retries to zero.
mov pktnum, 0 ;Set the packet number to zero.
mov numtry, 0 ;Set the number of tries to zero.
mov cxzflg, 0 ;[19f] reset ^X/^Z flag
call pretry
mov state, 'R' ;Set the state to receive initiate.
read2: call pnmpkt
mov ah, state ;Get the state.
cmp ah, 'D' ;Are we in the data send 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
mov dx, offset infms3 ;Plus a little cuteness.
cmp cxzflg,0 ;[19f] an interruption?
je read59 ;[19f] no - do normal thing
mov dx, offset infms7 ;[19f] substitute 'interrupted' message.
read59: call fnstat
ret
read6: mov dx, offset infms4 ;Plus a little cuteness.
call fnstat
ret
; Receive routines
; Receive init
rinit: mov ah, numtry ;Get the number of tries.
cmp ah, imxtry ;Have we reached the maximum number of tries?
jl rinit2
mov dx, offset ermes7 ;Print this error and die.
jmp fatal
rinit2: inc ah ;Increment it.
mov numtry, ah ;Save the updated number of tries.
call rpack ;Get a packet.
jmp nak ; Trashed packet: nak, retry.
cmp ah, 'S' ;Is it a send initiate packet?
jne rinit3 ;If not see if its an error.
mov ebquot, 'Y' ;Initialize my 8th-bit quote flag ;[29g]
mov ah, numtry ;Get the number of tries.
mov oldtry, ah ;Save it.
mov numtry, 0 ;Reset the number of tries.
mov ax, argblk ;Returned packet number. (Synchronize them.)
call incpkt ;Increment the packet number.
mov ax, 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 argbk1, ax ;Store the returned number of arguments.
call ack1 ;ACK the packet.
jmp abort
mov ah, 'F' ;Set the state to file send.
mov state, ah
ret
rinit3: cmp ah, 'E' ;Is it an error packet?
jne rinit4
call error
rinit4: jmp abort
; Receive file
rfile: cmp numtry, maxtry ;Have we reached the maximum number of tries?
jl rfile1
mov dx, offset ermes8 ;Print this error and die.
jmp fatal
rfile1: inc numtry ;Save the updated number of tries.
call rpack ;Get a packet.
jmp nak ; Trashed packet: nak, retry.
cmp ah, 'S' ;Is it a send initiate packet?
jne rfile2 ; No, try next type.
cmp oldtry, imxtry ;Have we reached the maximum number of tries?
jl rfil12 ;If not proceed.
mov dx, offset ermes7 ;Print this error and die.
jmp fatal
rfil12: call chkpol ;Check the packet number, is it right?
jmp nak ;No, NAK and try again.
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 argbk1, ax ;Save the number of arguments.
call reack ;Re-ACK the old packet.
jmp abort
ret
rfile2: cmp ah, 'Z' ;Is it an EOF packet?
jne rfile3 ; No, try next type.
cmp oldtry, maxtry ;Have we reached the maximum number of tries?
jl rfil21 ;If not proceed.
mov dx, offset ermes9 ;Print this error and die.
jmp fatal
rfil21: call chkpol ;Check the packet number, is it right?
jmp nak ;No, NAK and try again.
mov argbk1, 0 ;No data.
call reack ;Re-ACK the previous packet
jmp abort
ret
rfile3: cmp ah, 'F' ;Start of file?
jne rfile4
call chkpeq ;Packet numbers equal?
jmp nak ; No, NAK it and try again.
call incpkt ;Increment the number of packets.
call gofil ;Get a file to write to.
jmp abort
call init1 ;Initialize all the file buffers.
call upack ;Update counters and ACK the packet.
jmp abort
mov state, 'D' ;Set the state to data receive.
ret
rfile4: cmp ah, 'B' ;End of transmission?
jne rfile5
call chkpeq ;Packet numbers equal?
jmp nak ; No, NAK it and try again.
call ack ;ACK the packet.
jmp abort
mov state, 'C' ;Set the state to complete.
ret
rfile5: cmp ah, 'E' ;Is it an error packet?
jne rfile6
call error
rfile6: jmp abort
; Receive data
rdata: cmp numtry, maxtry ;Get the number of tries.
jl rdata1
mov dx, offset erms10 ;Print this error and die.
jmp fatal
rdata1: inc numtry ;Save the updated number of tries.
call rpack ;Get a packet.
jmp nak ; Trashed packet: nak, retry.
cmp ah, 'D' ;Is it a data packet?
je rdat11
jmp rdata2 ; No, try next type.
rdat11: call chkpeq ;Packet numbers equal?
jmp rdat12 ; No, check if previous packet.
call incpkt ;Increment the number of packets.
mov ax, argbk1 ;Get the length of the data.
cmp cxzflg, 0 ;[19f] interrupt requested?
jne rdat1a ;[19f] yes - skip put to file.
call ptchr
jmp abort ; Unable to write out chars;abort.
call upack ;ACK the packet.
jmp abort
ret
rdat1a: mov bx, offset data ;[19f] data location
mov ah, cxzflg ;[19f] get the ^X/^Z flag
mov [bx], ah ;[19f] stick it in the packet
mov argbk1, 1 ;[19f] data length is 1
call uupack ;[19f] ACK the packet (without zeroing argbk1)
jmp abort ;[19f]
ret ;[19f]
rdat12: cmp oldtry, maxtry ;Have we reached the maximum number of tries?
jl rdat13 ;If not proceed.
mov dx, offset erms10 ;Print this error and die.
jmp fatal
rdat13: call chkpol ;Check the packet number, is it right?
jmp nak ;No, NAK it and try again.
mov argbk1, 0 ;No data.
call reack ;Re-ACK the previous packet.
jmp abort
ret
rdata2: cmp ah, 'F' ;Start of file?
jne rdata3 ; No, try next type.
cmp oldtry, maxtry ;Have we reached the maximum number of tries?
jl rdat21 ;If not proceed.
mov dx, offset ermes8 ;Print this error and die.
jmp fatal
rdat21: call chkpol ;Check the packet number, is it right?
jmp nak ; No, NAK it and try again.
mov argbk1, 0 ;No data.
call reack ;Re-ACK the previous packet
jmp abort
ret
rdata3: cmp ah, 'Z' ;Is it a EOF packet?
je rdat32
jmp rdata4 ;Try and see if its an error.
rdat32: call chkpeq ;Packet numbers equal?
jmp nak ; No, NAK it and try again.
call incpkt ;Increment the packet number.
cmp cxzflg, 0 ;This file interrupted? [19f] start
jne rdat3a ;yes jump
cmp argbk1, 1 ;1 byte of data in EOF packet?
jmp rdat3b ;no - finish up file
mov bx, offset data ;pointer to data
mov ah, [bx] ;get the data
cmp ah, 'D' ;is it D as in Discard?
jne rdat3b ;no - finish writing file
rdat3a: mov dx, offset fcb ;get file's fcb
call delete ;delete the file.
cmp cxzflg, 'X' ;Kill one file or batch?
jne rdat37 ;whole batch - leave flag
mov cxzflg, 0 ;clear flag
call intmsg ;clear message
jmp rdat37 ;go to clean up. [19f] end
rdat3b: mov bx, bufpnt ;Get the dma pointer.
mov ax, 80H
sub ax, chrcnt ;Get the number of chars left in the DMA.
cmp ax, 80H
jne rdat34
call outbuf ;Write out buffer if no room for ^Z.
jmp abort
jmp rdat36 ;Go close the file.
rdat34: mov cl, 'Z'-100O ;Put in a ^Z for EOF.
mov [bx], cl
inc ax
dec chrcnt
mov cx, chrcnt
mov temp, cx
inc bx
rdt3: inc ax
cmp ax, 80H
jg rdat35 ;Pad till full.
mov cl, 1AH ;Use control-Z's ;[13]
mov [bx], cl
inc bx
jmp rdt3
rdat35: call outbuf ;Output the last buffer.
jmp abort ; Give up if the disk is full.
rdat36: mov dx, offset fcb
call closf ;Close up the file.
rdat37: call upack ;ACK the packet.
jmp abort
mov state, 'F'
ret
rdata4: cmp ah, 'E' ;Is it an error packet.
jne rdata5
call error
rdata5: jmp abort
; Send a file.
send: cmp wldflg,0FFh
je send12
mov dircnt,0 ;If not wild, just use the name in the FCB
mov dindex,0
call getopn ;Open the file
jmps send19
send12: call getwld ;If wild, get sorted list of matching names
jmp r ; on error, message already printed
mov dindex,0 ;Start at first one
call getfil ;Get and open first file
jmp r
send19: call init ;Paint the screen and initialize file buffers.
call cfibf ;Clear out any stacked NAKs.
mov pktnum, 0 ;Set the packet number to zero.
mov numtry, 0 ;Set the number of tries to zero.
mov numpkt, 0 ;Set the number of packets to zero.
mov numrtr, 0 ;Set the number of retries to zero.
call pretry ;Print the number of retries.
mov state,'S' ;Set the state to receive initiate.
send2: call pnmpkt ;Print the number of packets.
cmp state, 'S' ;Are we in the send initiate state?
jne send3
call sinit
jmp send2
send3: cmp state, 'F' ;Are we in the file send state?
jne send4
call sfile ;Call send file.
jmp send2
send4: cmp state, 'D' ;Are we in the data send state?
jne send5
call sdata
jmp send2
send5: cmp state, 'Z' ;Are we in the EOF state?
jne send6
call seof
jmp send2
send6: cmp state, 'B' ;Are we in the eot state?
jne send7
call seot
jmp send2
send7: cmp state, 'C' ;Are we in the send complete state?
jne send8
mov dx, offset infms3 ;Plus a little cuteness.
cmp cxzflg, 0 ;[19f] Interrupted?
je send7a ;[19f] no
mov dx, offset infms7 ;[19f] substitute "interrupted" message
send7a: call fnstat
ret
send8: mov dx, offset infms4 ;Plus a little cuteness.
call fnstat
ret
; Send routines
; Send initiate
sinit: cmp numtry, imxtry ;Have we reached the maximum number of tries?
jl sinit2
mov dx, offset erms14
jmp fatal
sinit2: mov ah, 'Y' ;Reset our quote capability ;[29g] begin
cmp parflg, parnon ;If we have parity,
je sini21 ; send our quote preference
mov ah, dqbin
sini21: mov ebquot, ah ;Set our quote capability ;[29g] end
inc numtry ;Save the updated 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 argbk1, ax ;Save the number of arguments.
mov ax, numpkt ;Get the packet number.
mov argblk, ax
mov ah, 'S' ;Send initiate packet.
call spack ;Send the packet.
jmp abort
call rpack ;Get a packet.
jmp r ; Trashed packet don't change state, retry.
cmp ah, 'Y' ;ACK?
jne sinit3 ;If not try next.
call chkpeq ;Is it the right packet number?
jmp nretry ;Increment the retries and go try again.
call incpkt ;Increment the packet number.
mov ax, argbk1 ;Get the number of pieces of data.
mov bx, offset data ;Pointer to the data.
call spar ;Read in the data.
mov ah, numtry ;Get the number of tries.
mov oldtry, ah ;Save it.
mov numtry, 0 ;Reset the number of tries.
mov state, 'F' ;Set the state to file send.
ret
sinit3: cmp ah, 'N' ;NAK?
jne sinit4 ;If not see if its an error.
call nretry
ret
sinit4: cmp ah, 'E' ;Is it an error packet?
jne sinit5
call error
sinit5: jmp abort
; Send file header
sfile: cmp numtry, maxtry ;Have we reached the maximum number of tries?
jl sfile1
mov dx, offset erms14
jmp fatal
sfile1: inc numtry ;Increment it.
mov cxzflg, 0 ;[19f] clear ^X/^Z flag
push ds
pop es
mov di, offset data ;Get a pointer to our data block.
mov si, offset fcb+1 ;Pointer to file name in FCB.
mov cx,11
sfil11: cmp cx,3 ;Separate file type with period
jne sfil12
mov al,'.'
stosb
sfil12: lodsb
and al,7Fh ;Strip off attribute bits
cmp al,' ' ;Printable, nonspace characters only
jbe sfil13
cmp al,7Fh
jae sfil13
stosb
sfil13: loop sfil11
mov byte ptr [di],'$' ;Terminate filename for printing
sub di, offset data
mov argbk1, di ;Save number of characters in name
call clrfln
mov dx, offset data ;Print file name.
call tmsg
mov ax, pktnum ;Get the packet number.
mov argblk, ax
mov ah, 'F' ;File header packet.
call spack ;Send the packet.
jmp abort
call rpack ;Get a packet.
jmp r ; Trashed packet don't change state, retry.
cmp ah, 'Y' ;ACK?
jne sfile2 ;If not try next.
call chkpeq ;Packet number right.
jmp nretry ;Increment the retries and go try again.
sfil14: call incpkt ;Increment the packet number.
call updat ;Update the number of tries.
sfil15: mov byte ptr fcb+20h,0 ;Set the record number to zero.
mov eoflag, 0 ;Indicate not EOF.
mov filflg, 0FFh ;Indicate file buffer empty.
call gtchr
jmp sfil16 ;Error go see if its EOF.
jmp sfil18 ;Got the chars, proceed.
sfil16: cmp ah, 0FFH ;Is it EOF?
je sfil17
jmp abort ;If not give up.
sfil17: mov state, 'Z' ;Set the state to EOF.
ret
sfil18: mov siz, ax
mov state, 'D' ;Set the state to data send.
ret
sfile2: cmp ah, 'N' ;NAK?
jne sfile3 ;Try if error packet.
call chkpom ;Is the packet's number one more than now?
jmp nretry ;Increment the retries and go try again.
jmp sfil14 ;If so, join the ACK.
sfile3: cmp ah, 'E' ;Is it an error packet.
jne sfile4
call error
sfile4: jmp abort
; Send data
sdata: cmp cxzflg, 0 ;[19f] Interrupt flag on?
je sdata0 ;[19f] no
mov state, 'Z' ;[19f] yes - abort sending file
ret
sdata0: cmp numtry, maxtry ;Have we reached the maximum number of tries?
jl sdata1
mov dx, offset erms14
jmp fatal
sdata1: inc numtry ;Increment it.
mov dx, offset data ;Get a pointer to our data block.
mov datptr, dx
mov dx, offset filbuf ;Pointer to chars to be sent.
mov cbfptr, dx
mov cx, 1 ;First char.
sdat11: mov bx, cbfptr
mov ah, [bx]
inc cbfptr
mov bx, datptr
mov [bx], ah ;Put the char in the data packet.
inc datptr ;Save position in data packet.
inc cx ;Increment the count.
cmp cx, siz ;Have we transfered that many?
jle sdat11 ;If not get another.
mov ax, siz ;Number of char in char buffer.
mov argbk1, ax
mov ax, pktnum ;Get the packet number.
mov argblk, ax
mov ah, 'D' ;Data packet.
call spack ;Send the packet.
jmp abort
call rpack ;Get a packet.
jmp r ; Trashed packet don't change state, retry.
cmp ah, 'Y' ;ACK?
jne sdata2 ;If not try next.
call chkpeq ;Right packet number?
jmp nretry ;Increment the retries and go try again.
sdat12: call incpkt ;Increment the packet number.
call updat ;Update the number of tries.
cmp argbk1,1 ;1 byte of data there? [19f] start
jne sdt12b ;no - go on
mov bx, offset data ;pointer to data
mov ah, [bx] ;get the data
cmp ah, 'X' ;an 'X'?
je sdt12a ;yes - go
cmp ah, 'Z' ;or a 'Z'
je sdt12a ;also go
jmp sdt12b ;neither one - go on
sdt12a: mov cxzflg, ah ;'X' or 'Z' - set the interrupt flag [19f] end
ret
sdt12b: call gtchr
jmp sdat13 ;Error go see if its EOF.
mov siz, ax ;Save the size of the data gotten.
ret
sdat13: cmp ah, 0FFH ;Is it EOF?
je sdat14
jmp abort ;If not give up.
sdat14: mov state, 'Z' ;Set the state to EOF.
ret
sdata2: cmp ah, 'N' ;NAK?
jne sdata3 ;See if is an error packet.
call chkpom ;Is the packet's number one more than now?
jmp nretry ;Increment the retries and go try again.
jmp sdat12
sdata3: cmp ah, 'E' ;Is it an error packet.
jne sdata4
call error
sdata4: jmp abort
; Send EOF
seof: cmp numtry, maxtry ;Have we reached the maximum number of tries?
jl seof1
mov dx, offset erms14
jmp fatal
seof1: inc numtry ;Increment it.
mov ax, pktnum ;Get the packet number.
mov argblk, ax
mov argbk1, 0 ;No data.
cmp cxzflg, 0 ;[19f] interrupt flag set?
je seof1a ;[19f] no - go on
mov bx, offset data ;[19f] point to data
mov ah, 'D' ;[19f] get 'D' as in Discard
mov [bx], ah ;[19f] stuff it into packet
mov argbk1, 1 ;[19f] set data length of 1
seof1a: mov ah, 'Z' ;EOF packet.
call spack ;Send the packet.
jmp abort
call rpack ;Get a packet.
jmp r ; Trashed packet don't change state, retry.
cmp ah, 'Y' ;ACK?
jne seof2 ;If not try next.
call chkpeq ;Is it the right packet number?
jmp nretry ;Increment the retries and go try again.
seof12: call incpkt ;Increment the packet number.
call updat ;Update the number of tries.
mov dx, offset fcb ;Close the file.
call closf
call getfil ;Get and open the next file.
jmp seof13 ; No more.
mov state, 'F' ;Set the state to file send.
cmp cxzflg, 'X' ;[19f] 'X' in interrupt flag?
mov cxzflg, 0 ;[19f] meantime reset it
jne sef13a ;[19f] no - go on
call intmsg ;[19f] clear interrupt message
sef13a: ret ;[19f] goodbye
seof13: mov state, 'B' ;Set the state to EOT.
ret
seof2: cmp ah, 'N' ;NAK?
jne seof3 ;Try and see if its an error packet.
call chkpom ;Is the packet's number one more than now?
jmp nretry ;Increment the retries and go try again.
jmp seof12
seof3: cmp ah, 'E' ;Is it an error packet?
jne seof4
call error
seof4: jmp abort
; Send EOT
seot: cmp numtry, maxtry ;Have we reached the maximum number of tries?
jl seot1
mov dx, offset erms14
jmp fatal
seot1: inc numtry ;Increment it.
mov ax, pktnum ;Get the packet number.
mov argblk, ax
mov argbk1, 0 ;No data.
mov ah, 'B' ;EOF packet.
call spack ;Send the packet.
jmp abort
call rpack ;Get a packet.
jmp r ;Trashed packet don't change state, retry.
cmp ah, 'Y' ;ACK?
jne seot2 ;If not try next.
call chkpeq ;Is it the right packet number.
jmp nretry ;Increment the retries and go try again.
seot12: call incpkt ;Increment the packet number.
call updat ;Update the number of tries.
mov state, 'C' ;Set the state to file send.
ret
seot2: cmp ah, 'N' ;NAK?
jne seot3 ;Is it error.
call chkpom ;Is the packet's number one more than now?
jmp nretry ;Increment the retries and go try again.
jmp seot12
seot3: cmp ah, 'E' ;Is it an error packet.
jne seot4
call error
seot4: jmp abort