(* receive related procedures are kept in this file *) procedure get_char(var character : integer); (* get an incoming character from a packet *) var temp, rec_data, rec_stat : integer; begin temp := 0; character := 0; abort := false; retry := false; repeat iobyte := port_iobyte; (* try to get char from kermit channel *) rec_stat := bios(1); if rec_stat <> 0 then (* there is a character pending *) if port_type_var = comm then (* handle comm with reader BDOS call *) character := bios(6) else character := bios(2); (* use console i/o for others *) iobyte := base_iobyte; (* check for a character from keyboard *) temp := bdos(6,$ff); if temp <> 0 then begin case temp of 4 : abort := true; (* ^D aborts for now *) $0d : retry := true; (* cr forces end of packet *) end; (* case *) end; until ((rec_stat <> 0) or abort or retry); (* condition for exit *) if parity_type_var <> no_parity then character := character and $7f; (* strip the parity bit *) end; procedure receive_packet; (* get a complete packet. *) var rec_char, temp : integer; check_char, temp_char : char; check_ok : boolean; checksum, count, index : integer; procedure get_p_length; (* After getting a ^A, start of packet, the next character should be the length of the packet. This procedure was pulled out of the main receive procedure to make it easier to handle a new packet coming in before the old one finished (characters lost, etc.) *) begin if not (abort or retry) then (* skip if forced by operator *) begin get_char(rec_char); (* we get a character *) checksum := rec_char; (* first char to checksum *) count := rec_char - 32; (* whats our packet length *) end; end; begin (* rec_packet *) checksum := 0; (* start with no checksum *) rec_packet := ''; (* no data in packet *) check_ok := false; (* if we haven't got a packet, it can't be any good *) packet_ok := false; (* same here *) repeat (* get ^A *) get_char(rec_char); until ((rec_char = 1) or abort or retry); get_p_length; (* we got a ^A so we need the length of the packet *) if not (abort or retry) then begin repeat get_char(rec_char); (* should be packet type and data *) if rec_char = 1 then (* got new start of packet *) begin (* clear ourselves out again *) rec_packet := ''; get_p_length; (* get new length *) end else (* must be a character *) begin rec_packet := rec_packet + chr(rec_char); (* add to packet *) checksum := checksum + rec_char; (* add in the checksum *) count := count - 1; (* decrement the character counter *) end; until (abort) or retry or (count = 0); packets_sent := packets_sent + 1; (* sent is a misnomer here *) if debug then (* show what we got *) begin gotoxy(1,12); write('rpack: '); for count := 1 to length(rec_packet) do (* print the packet *) begin temp_char := rec_packet[count]; (* dummy for printing *) if (temp_char > chr(127)) then (* 8th bit set *) begin write(''''); (* print ' to show 8th bit set *) temp_char := chr(ord(temp_char) and $7f); (* strip eighth bit *) end; (* and fall through *) if (temp_char < ' ') then (* print ctl char with ^ *) write('^' + ctl(temp_char)) else write(temp_char); (* must be printable *) end; end; if not abort then (* lets check what we can about packet *) begin checksum := checksum - rec_char; (* subtract chksum char *) check_char := char40((checksum + ((checksum and 192) div 64)) and 63); if debug then (* show the checksum expected and received *) begin gotoxy(1,15); write('Received checksum: ',rec_packet[length(rec_packet)], ' Calculated checksum: ', check_char); end; if check_char = rec_packet[length(rec_packet)] then check_ok := true; (* good checksum *) rec_packet_num := unchar(rec_packet[1]); (* what kind of packet *) case rec_packet[2] of 'B' : packet_type := break_pack; 'D' : packet_type := data_pack; 'E' : packet_type := error_pack; 'F' : packet_type := header_pack; 'N' : packet_type := nak_pack; 'S' : packet_type := send_pack; 'T' : packet_type := reserved_pack; 'Y' : packet_type := ack_pack; 'Z' : packet_type := end_pack; else packet_type := unknown; end; (* case *) if length(rec_packet) > 3 then (* clean off the packet number, packet type, and checksum *) begin delete(rec_packet,1,2); delete(rec_packet,length(rec_packet),1); end; if (check_ok) and (packet_type <> unknown) then packet_ok := true; if debug then begin gotoxy(1,18); write('packet ok: ',packet_ok); end; end; end; end; (* rec_packet *)