home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBBS / ECO_ZMOD.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-12-29  |  76.7 KB  |  2,693 lines

  1. (*
  2.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  3.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  4.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  5.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  6.     ▓▓▓▓▓▓▓▓·──                                              ──·▓▓▓▓▓▓▓▓▓▓▓
  7.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  8.     ▓▓▓▓▓▓▓▓   ECO_ZMOD was conceived, designed and written     ░░▓▓▓▓▓▓▓▓▓
  9.     ▓▓▓▓▓▓▓▓   by Floor A.C. Naaijkens for                      ░░▓▓▓▓▓▓▓▓▓
  10.     ▓▓▓▓▓▓▓▓   UltiHouse Software / The ECO Group.              ░░▓▓▓▓▓▓▓▓▓
  11.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  12.     ▓▓▓▓▓▓▓▓   (C) MCMXCII by EUROCON PANATIONAL CORPORATION.   ░░▓▓▓▓▓▓▓▓▓
  13.     ▓▓▓▓▓▓▓▓   All Rights Reserved for The ECO Group.           ░░▓▓▓▓▓▓▓▓▓
  14.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  15.     ▓▓▓▓▓▓▓▓   All Credits to J.R.Louvau, unit conversion and   ░░▓▓▓▓▓▓▓▓▓
  16.     ▓▓▓▓▓▓▓▓   ECO_ZMOD by Floor Naaijkens. Unit was extracted  ░░▓▓▓▓▓▓▓▓▓
  17.     ▓▓▓▓▓▓▓▓   from various PibTerm routines by Philip Burns.   ░░▓▓▓▓▓▓▓▓▓
  18.     ▓▓▓▓▓▓▓▓   Update for combined FOSSIL/RS232 by UltiHouse.   ░░▓▓▓▓▓▓▓▓▓
  19.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  20.     ▓▓▓▓▓▓▓▓·──                                              ──·░░▓▓▓▓▓▓▓▓▓
  21.     ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓
  22.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  23.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  24.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  25. *)
  26.  
  27. {$A-,B-,D-,E-,F-,I-,L-,N-,O-,R-,S-,V-}
  28. {$M 65520, 0, 655360}
  29. unit eco_zmod;
  30.  
  31. interface
  32. uses
  33.   eco_lib,
  34.  
  35.   crt, dos, 
  36.  
  37.   eco_fosl, eco_asyn
  38.   
  39.   ;
  40.  
  41.  
  42.  
  43. const
  44.   zmodemlogging: boolean = false;
  45.  
  46. var
  47.   alreadycarrier : boolean;
  48.   filenum        :    word;
  49.  
  50.  
  51.   function zmodem_receive(
  52.     path: string; comport: word; baudrate: longint; init: boolean
  53.   ): boolean;
  54.  
  55.  
  56.   function zmodem_send(
  57.     pathname: string; lastfile: boolean; comport: word; baudrate: longint;
  58.     init: boolean
  59.   ): boolean;
  60.  
  61.   procedure z_message(s: string);
  62.   procedure z_setcomport(port: byte; fossiloverride: boolean);
  63.   procedure z_sendcan;
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71. implementation
  72.  
  73.  
  74.  
  75.  
  76. const
  77.   zbufsize = 1024;
  78.  
  79.  
  80. type
  81.   hdrtype = array[0..3] of byte;
  82.   buftype = array[0..zbufsize-1] of byte;
  83.  
  84. var
  85.   rxpos           :  longint;   { file position received from z_getheader }
  86.   rxhdr           :  hdrtype;   {                      receive header var }
  87.   rxtimeout,
  88.   rxtype,
  89.   rxframeind      :  integer;
  90.   attn            :  buftype;
  91.   secbuf          :  buftype;
  92.   fname           :   string;
  93.   fmode           :  integer;
  94.   ftime,
  95.   fsize,
  96.   oldl            :  longint;
  97.   usefossil,
  98.   usecrc32        :  boolean;
  99.   zcps, zerrors   :     word;
  100.   txhdr           :  hdrtype;
  101.   txpos, ztime,
  102.   totalbytes,  
  103.   curfsize        :  longint;
  104.   comport         :     byte;
  105.  
  106.  
  107.  
  108.  
  109. const
  110.   lastsent: byte = 0;
  111.   tpzver = 'ECO-LINK 3.52';
  112.  
  113.   zport: word = 1;
  114.   zbaud: longint = 0;
  115.  
  116.   zpad = 42;  { '*' }
  117.   zdle = 24;  { ^x  }
  118.   zdlee = 88;
  119.   zbin = 65;  { 'A' }
  120.   zhex = 66;  { 'B' }
  121.   zbin32 = 67;{ 'C' }
  122.   zrqinit = 0;
  123.   zrinit = 1;
  124.   zsinit = 2;
  125.   zack = 3;
  126.   zfile = 4;
  127.   zskip = 5;
  128.   znak = 6;
  129.   zabort = 7;
  130.   zfin = 8;
  131.   zrpos = 9;
  132.   zdata = 10;
  133.   zeof = 11;
  134.   zferr = 12;
  135.   zcrc = 13;
  136.   zchallenge = 14;
  137.   zcompl = 15;
  138.   zcan = 16;
  139.   zfreecnt = 17;
  140.   zcommand = 18;
  141.   zstderr = 19;
  142.   zcrce = 104; { 'h' }
  143.   zcrcg = 105; { 'i' }
  144.   zcrcq = 106; { 'j' }
  145.   zcrcw = 107; { 'k' }
  146.   zrub0 = 108; { 'l' }
  147.   zrub1 = 109; { 'm' }
  148.   zok = 0;
  149.   zerror = -1;
  150.   ztimeout = -2;
  151.   rcdo = -3;
  152.   fubar = -4;
  153.   gotor = 256;
  154.   gotcrce = 360; { 'h' or 256 }
  155.   gotcrcg = 361; { 'i' "   "  }
  156.   gotcrcq = 362; { 'j' "   "  }
  157.   gotcrcw = 363; { 'k' "   "  }
  158.   gotcan = 272;  { can or  "  }
  159.  
  160. { xmodem paramaters }
  161.   enq = 5;
  162.   can = 24;
  163.   xoff = 19;
  164.   xon = 17;
  165.   soh = 1;
  166.   stx = 2;
  167.   eot = 4;
  168.   ack = 6;
  169.   nak = 21;
  170.   cpmeof = 26;
  171.  
  172. { byte positions }
  173.   zf0 = 3;
  174.   zf1 = 2;
  175.   zf2 = 1;
  176.   zf3 = 0;
  177.   zp0 = 0;
  178.   zp1 = 1;
  179.   zp2 = 2;
  180.   zp3 = 3;
  181.  
  182. { bit masks for zrinit }
  183.   canfdx  = 1;    { can handle full-duplex         (yes for pc's) }
  184.   canovio = 2;    { can overlay disk and serial i/o (ditto)       }
  185.   canbrk  = 4;    { can send a break - true but superfluous       }
  186.   cancry  = 8;    { can encrypt/decrypt - not defined yet         }
  187.   canlzw  = 16;   { can lz compress - not defined yet             }
  188.   canfc32 = 32;   { can use 32 bit crc frame checks - true        }
  189.   escall  = 64;   { escapes all control chars. not implemented    }
  190.   esc8    = 128;  { escapes the 8th bit. not implemented          }
  191.  
  192. { bit masks for zsinit }
  193.   tescctl =  64;
  194.   tesc8   = 128;
  195.  
  196. { paramaters for zfile }
  197. { zf0 }
  198.   zcbin   = 1;
  199.   zcnl    = 2;
  200.   zcresum = 3;
  201. { zf1 }
  202.   zmnew   = 1;   {i haven't implemented these as of yet - most are}
  203.   zmcrc   = 2;   {superfluous on a bbs - would be nice from a comm}
  204.   zmapnd  = 3;   {programs' point of view however                 }
  205.   zmclob  = 4;
  206.   zmspars = 5;
  207.   zmdiff  = 6;
  208.   zmprot  = 7;
  209. { zf2 }
  210.   ztlzw   = 1;   {encryption, compression and funny file handling }
  211.   ztcrypt = 2;   {flags - my docs (03/88) from omen say these have}
  212.   ztrle   = 3;   {not been defined yet                            }
  213. { zf3 }
  214.   zcack1  = 1;   {god only knows...                               }
  215.  
  216.  
  217.  
  218.  
  219.   procedure z_setcomport(port: byte; fossiloverride: boolean);
  220.   begin
  221.     comport := port; usefossil := fos_present_(comport) and not(fossiloverride);
  222.   end;
  223.  
  224.  
  225.  
  226.   function  __packfil(str: string; size: byte): string;
  227.   var i,ii: byte;
  228.   begin
  229.     if size<15 then size := 15; str := fexpand(str);
  230.     if length(str) <= size then __packfil := str else begin
  231.       while length(str) > size+1 do begin
  232.         i := pos('\',str); inc(i); ii := i; while str[ii]<>'\' do inc(ii);
  233.         inc(ii); delete(str,i,ii-i);
  234.       end; i := pos('\',str); delete(str,i,1); __packfil := str
  235.     end;
  236.   end;
  237.  
  238.  
  239.  
  240.  
  241.   function __pntstr(n: longint): string;
  242.   var
  243.     tmpnrstr,
  244.     tmpcvtstr   : string;
  245.     tab, i,
  246.     len_numstr,
  247.     len_pnts    :   byte;
  248.  
  249.   begin
  250.     str(n, tmpnrstr); tab := 0;
  251.     len_numstr := length(tmpnrstr);
  252.     len_pnts := (len_numstr -1) div 3;
  253.     tmpcvtstr[0] := chr(len_numstr + len_pnts);
  254.  
  255.     tmpcvtstr[len_pnts +len_numstr -tab] := tmpnrstr[len_numstr];
  256.     for i := len_numstr-1 downto 1 do begin
  257.       if ((len_numstr -i) mod 3 =0) then begin
  258.         tmpcvtstr[len_pnts +i -tab] := '.'; inc(tab)
  259.       end;
  260.       tmpcvtstr[len_pnts +i -tab] := tmpnrstr[i];
  261.     end;
  262.     __pntstr := copy(tmpcvtstr, 1, len_numstr +len_pnts);
  263.   end;
  264.  
  265.  
  266.  
  267.  
  268.  
  269.   function z_charavail: boolean;
  270.   (* see if there is a character coming in *)
  271.   begin
  272.     if usefossil then z_charavail := fos_avail_(comport) else
  273.       z_charavail := async_buffer_check
  274.   end;
  275.  
  276.  
  277.  
  278.   procedure z_clearinbound;
  279.   (* throw away any pending input to clear the line *)
  280.   var n: integer;
  281.   begin
  282.     if usefossil then fos_kill_in_(comport) else begin
  283.       while (async_carrier_detect) and (async_buffer_check) do
  284.         async_receive_with_timeout(1,n)
  285.     end;
  286.   end;
  287.  
  288.  
  289.   procedure z_clearoutbound;
  290.   (* throw away any pending output in the buffer *)
  291.   begin
  292.     if usefossil then fos_flush_(comport) else
  293.       async_flush_output_buffer;
  294.   end;
  295.  
  296.   procedure z_flushoutbound;
  297.   begin
  298.     if usefossil then fos_kill_out_(comport) else begin
  299.       repeat until (
  300.         (not async_carrier_detect) or
  301.         (async_obuffer_head = async_obuffer_tail)
  302.       )
  303.     end;
  304.   end;
  305.  
  306.  
  307.   procedure z_sendbreak;
  308.   (* send a break signal *)
  309.   begin
  310.      if not usefossil then async_send_break
  311.   end;
  312.  
  313.   
  314.   procedure z_sendbyte(b: byte);
  315.   (* output one byte *)
  316.   begin
  317.     if usefossil then fos_write_(comport, chr(b)) else async_send(chr(b))
  318.   end;
  319.  
  320.  
  321.   function z_receivebyte: integer;
  322.   (* input one byte (n.b.: returns an integer!) *)
  323.   var
  324.      n: integer;
  325.   begin
  326.     if usefossil then z_receivebyte := ord(fos_receive_(comport)) else begin
  327.       async_receive_with_timeout(0,n);
  328.       z_receivebyte := (n and $00ff)
  329.     end;
  330.   end;
  331.  
  332.  
  333.   function z_carrier: boolean;
  334.   (* checks for the presence of a carrier *)
  335.   begin
  336.     if usefossil then z_carrier := alreadycarrier or (fos_cd_(comport)) else
  337.       z_carrier := (async_carrier_detect)
  338.   end;
  339.  
  340.   
  341.   procedure z_asyncoff;
  342.   var
  343.      i : integer;
  344.      m : integer;
  345.   begin  (* async_close *)
  346.     if not usefossil then begin
  347.       (* read the rbr and reset any pending error conditions. *)
  348.       (* first turn off the divisor access latch bit to allow *)
  349.       (* access to rbr, etc.                                  *)
  350.       inline($fa);  (* disable interrupts *)
  351.       port[uart_lcr + async_base] := port[uart_lcr + async_base] and $7f;
  352.       (* read the line status register to reset any errors *)
  353.       (* it indicates                                      *)
  354.       i := port[uart_lsr + async_base];
  355.       (* read the receiver buffer register in case it *)
  356.       (* contains a character                         *)
  357.       i := port[uart_rbr + async_base];
  358.       (* enable the irq on the 8259 controller *)
  359.       i := port[i8088_imr];  (* get the interrupt mask register *)
  360.       m := (1 shl async_irq) xor $00ff;
  361.       port[i8088_imr] := i and m;
  362.       (* enable out2 on 8250 *)
  363.       i := port[uart_mcr + async_base];
  364.       port[uart_mcr + async_base] := i or $0b;
  365.       (* enable the data ready interrupt on the 8250 *)
  366.       port[uart_ier + async_base] := $0f;
  367.       (* re-enable 8259 *)
  368.       port[$20] := $20;
  369.       inline($fb); (* enable interrupts *)
  370.       if async_open_flag then begin
  371.         (* disable the irq on the 8259 *)
  372.         inline($fa);                 (* disable interrupts *)
  373.         i := port[i8088_imr];        (* get the interrupt mask register *)
  374.         m := 1 shl async_irq;        (* set mask to turn off interrupt  *)
  375.         port[i8088_imr] := i or m;   (* disable the 8250 interrupts *)
  376.         port[uart_ier + async_base] := 0;
  377.           (* disable out2, rts, out1 on the 8250, but *)
  378.           (* possibly leave dtr enabled.              *)
  379.         port[uart_mcr + async_base] := 1;
  380.         inline($fb);                 (* enable interrupts *)
  381.           (* re-initialize our data areas so we know *)
  382.           (* the port is closed                      *)
  383.         async_open_flag := false;
  384.         async_xoff_sent := false;
  385.           (* restore the previous interrupt pointers *)
  386.         setintvec( async_irq + 8 , async_save_iaddr );
  387.           i := port[uart_lsr + async_base];
  388.           (* read the receiver buffer register in case it *)
  389.           (* contains a character                         *)
  390.         i := port[uart_rbr + async_base];
  391.           (* enable the irq on the 8259 controller *)
  392.         i := port[i8088_imr];  (* get the interrupt mask register *)
  393.         m := (1 shl async_irq) xor $00ff;
  394.         port[i8088_imr] := i and m;
  395.           (* enable out2 on 8250 *)
  396.         i := port[uart_mcr + async_base];
  397.         port[uart_mcr + async_base] := i or $0b;
  398.           (* enable the data ready interrupt on the 8250 *)
  399.         port[uart_ier + async_base] := $0f;
  400.           (* re-enable 8259 *)
  401.         port[$20] := $20;
  402.         inline($fb); (* enable interrupts *)
  403.       end;
  404.     end;
  405.   end; { async_close }
  406.  
  407.  
  408.  
  409.   function z_asyncon(zport: word; zbaud: longint): boolean;
  410.   begin
  411.     if usefossil then z_asyncon := fos_present_(comport) else begin
  412.       async_do_cts := false;
  413.       async_do_dsr := false;
  414.       async_do_xonxoff := false;
  415.       async_hard_wired_on := false;
  416.       async_break_length := 500;
  417.       async_init(2048,2048,0,0,0);
  418.       z_asyncon := async_open(zport, zbaud, 'N', 8, 1)
  419.     end;
  420.   end;
  421.  
  422.  
  423.  
  424. (* crctab calculated by mark g. mendel, network systems corporation *)
  425. const
  426.   crctab: array[0..255] of word = (
  427.     $0000,  $1021,  $2042,  $3063,  $4084,  $50a5,  $60c6,  $70e7,
  428.     $8108,  $9129,  $a14a,  $b16b,  $c18c,  $d1ad,  $e1ce,  $f1ef,
  429.     $1231,  $0210,  $3273,  $2252,  $52b5,  $4294,  $72f7,  $62d6,
  430.     $9339,  $8318,  $b37b,  $a35a,  $d3bd,  $c39c,  $f3ff,  $e3de,
  431.     $2462,  $3443,  $0420,  $1401,  $64e6,  $74c7,  $44a4,  $5485,
  432.     $a56a,  $b54b,  $8528,  $9509,  $e5ee,  $f5cf,  $c5ac,  $d58d,
  433.     $3653,  $2672,  $1611,  $0630,  $76d7,  $66f6,  $5695,  $46b4,
  434.     $b75b,  $a77a,  $9719,  $8738,  $f7df,  $e7fe,  $d79d,  $c7bc,
  435.     $48c4,  $58e5,  $6886,  $78a7,  $0840,  $1861,  $2802,  $3823,
  436.     $c9cc,  $d9ed,  $e98e,  $f9af,  $8948,  $9969,  $a90a,  $b92b,
  437.     $5af5,  $4ad4,  $7ab7,  $6a96,  $1a71,  $0a50,  $3a33,  $2a12,
  438.     $dbfd,  $cbdc,  $fbbf,  $eb9e,  $9b79,  $8b58,  $bb3b,  $ab1a,
  439.     $6ca6,  $7c87,  $4ce4,  $5cc5,  $2c22,  $3c03,  $0c60,  $1c41,
  440.     $edae,  $fd8f,  $cdec,  $ddcd,  $ad2a,  $bd0b,  $8d68,  $9d49,
  441.     $7e97,  $6eb6,  $5ed5,  $4ef4,  $3e13,  $2e32,  $1e51,  $0e70,
  442.     $ff9f,  $efbe,  $dfdd,  $cffc,  $bf1b,  $af3a,  $9f59,  $8f78,
  443.     $9188,  $81a9,  $b1ca,  $a1eb,  $d10c,  $c12d,  $f14e,  $e16f,
  444.     $1080,  $00a1,  $30c2,  $20e3,  $5004,  $4025,  $7046,  $6067,
  445.     $83b9,  $9398,  $a3fb,  $b3da,  $c33d,  $d31c,  $e37f,  $f35e,
  446.     $02b1,  $1290,  $22f3,  $32d2,  $4235,  $5214,  $6277,  $7256,
  447.     $b5ea,  $a5cb,  $95a8,  $8589,  $f56e,  $e54f,  $d52c,  $c50d,
  448.     $34e2,  $24c3,  $14a0,  $0481,  $7466,  $6447,  $5424,  $4405,
  449.     $a7db,  $b7fa,  $8799,  $97b8,  $e75f,  $f77e,  $c71d,  $d73c,
  450.     $26d3,  $36f2,  $0691,  $16b0,  $6657,  $7676,  $4615,  $5634,
  451.     $d94c,  $c96d,  $f90e,  $e92f,  $99c8,  $89e9,  $b98a,  $a9ab,
  452.     $5844,  $4865,  $7806,  $6827,  $18c0,  $08e1,  $3882,  $28a3,
  453.     $cb7d,  $db5c,  $eb3f,  $fb1e,  $8bf9,  $9bd8,  $abbb,  $bb9a,
  454.     $4a75,  $5a54,  $6a37,  $7a16,  $0af1,  $1ad0,  $2ab3,  $3a92,
  455.     $fd2e,  $ed0f,  $dd6c,  $cd4d,  $bdaa,  $ad8b,  $9de8,  $8dc9,
  456.     $7c26,  $6c07,  $5c64,  $4c45,  $3ca2,  $2c83,  $1ce0,  $0cc1,
  457.     $ef1f,  $ff3e,  $cf5d,  $df7c,  $af9b,  $bfba,  $8fd9,  $9ff8,
  458.     $6e17,  $7e36,  $4e55,  $5e74,  $2e93,  $3eb2,  $0ed1,  $1ef0
  459.   );
  460.  
  461.  
  462.  
  463. (*
  464.  * updcrc derived from article Copyright (C) 1986 Stephen Satchell.
  465.  *  NOTE: First argument must be in range 0 to 255.
  466.  *        Second argument is referenced twice.
  467.  *
  468.  * Programmers may incorporate any or all code into their programs,
  469.  * giving proper credit within the source. Publication of the
  470.  * source routines is permitted so long as proper credit is given
  471.  * to Stephen Satchell, Satchell Evaluations and Chuck Forsberg,
  472.  * Omen Technology.
  473.  *)
  474.   function updcrc(cp: byte; crc: word): word;
  475.   begin { updcrc }
  476.     updcrc := crctab[((crc shr 8) and 255)] xor (crc shl 8) xor cp
  477.   end;
  478.  
  479.  
  480.  
  481.  
  482. { use a type longint variable to store the crc value.                     }
  483. { initialise the variable to $ffffffff before running the crc routine.    }
  484. { very important!!!! -> this routine was developed for data communications}
  485. { and returns the crc bytes in low to high order, not byte reversed!      }
  486. { to turn the valu into a 'normal' longint, you must reverse the bytes!   }
  487. { e.g.                                                                    }
  488. { var                                                                     }
  489. {    l, crc: longint;                                                     }
  490. {    list: array[0..1023] of byte;                                        }
  491. {    counter: integer;                                                    }
  492. {                                                                         }
  493. { begin                                                                   }
  494. {    crc := $ffffffff;                           (* initialise  *)        }
  495. {    fillchar(list,sizeof(list),1);              (* dummy array *)        }
  496. {    for counter := 0 to (pred(sizeof(list))) do (* run thru    *)        }
  497. {       crc := updc32(buf[counter],crc);         (* finding crc *)        }
  498. {    for counter := 1 to 4 do                    (* reverse     *)        }
  499. {       l := (l shl 8) or byte(crc);             (* the bytes   *)        }
  500. {    (* l now contains the 'normalized' crc *)                            }
  501. {                                                                         }
  502. (* converted to turbo pascal (tm) v4.0 march, 1988 by j.r.louvau       *)
  503. (* copyright (c) 1986 gary s. brown.  you may use this program, or     *)
  504. (* code or tables extracted from it, as desired without restriction.   *)
  505. (*                                                                     *)
  506. (* first, the polynomial itself and its table of feedback terms.  the  *)
  507. (* polynomial is                                                       *)
  508. (* x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0 *)
  509. (* note that we take it "backwards" and put the highest-order term in  *)
  510. (* the lowest-order bit.  the x^32 term is "implied"; the lsb is the   *)
  511. (* x^31 term, etc.  the x^0 term (usually shown as "+1") results in    *)
  512. (* the msb being 1.                                                    *)
  513. (*                                                                     *)
  514. (* note that the usual hardware shift register implementation, which   *)
  515. (* is what we're using (we're merely optimizing it by doing eight-bit  *)
  516. (* chunks at a time) shifts bits into the lowest-order term.  in our   *)
  517. (* implementation, that means shifting towards the right.  why do we   *)
  518. (* do it this way?  because the calculated crc must be transmitted in  *)
  519. (* order from highest-order term to lowest-order term.  uarts transmit *)
  520. (* characters in order from lsb to msb.  by storing the crc this way,  *)
  521. (* we hand it to the uart in the order low-byte to high-byte; the uart *)
  522. (* sends each low-bit to hight-bit; and the result is transmission bit *)
  523. (* by bit from highest- to lowest-order term without requiring any bit *)
  524. (* shuffling on our part.  reception works similarly.                  *)
  525. (*                                                                     *)
  526. (* the feedback terms table consists of 256, 32-bit entries.  notes:   *)
  527. (*                                                                     *)
  528. (*     the table can be generated at runtime if desired; code to do so *)
  529. (*     is shown later.  it might not be obvious, but the feedback      *)
  530. (*     terms simply represent the results of eight shift/xor opera-    *)
  531. (*     tions for all combinations of data and crc register values.     *)
  532. (*                                                                     *)
  533. (*     the values must be right-shifted by eight bits by the "updcrc"  *)
  534. (*     logic; the shift must be unsigned (bring in zeroes).  on some   *)
  535. (*     hardware you could probably optimize the shift in assembler by  *)
  536. (*     using byte-swap instructions.                                   *)
  537. (*     polynomial $edb88320                                            *)
  538. (*                                                                     *)
  539.  
  540.  
  541. const
  542.   crc_32_tab: array[0..255] of longint = (
  543.    $00000000, $77073096, $ee0e612c, $990951ba, $076dc419, $706af48f, $e963a535,
  544.    $9e6495a3, $0edb8832, $79dcb8a4, $e0d5e91e, $97d2d988, $09b64c2b, $7eb17cbd,
  545.    $e7b82d07, $90bf1d91, $1db71064, $6ab020f2, $f3b97148, $84be41de, $1adad47d,
  546.    $6ddde4eb, $f4d4b551, $83d385c7, $136c9856, $646ba8c0, $fd62f97a, $8a65c9ec,
  547.    $14015c4f, $63066cd9, $fa0f3d63, $8d080df5, $3b6e20c8, $4c69105e, $d56041e4,
  548.    $a2677172, $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b, $35b5a8fa, $42b2986c,
  549.    $dbbbc9d6, $acbcf940, $32d86ce3, $45df5c75, $dcd60dcf, $abd13d59, $26d930ac,
  550.    $51de003a, $c8d75180, $bfd06116, $21b4f4b5, $56b3c423, $cfba9599, $b8bda50f,
  551.    $2802b89e, $5f058808, $c60cd9b2, $b10be924, $2f6f7c87, $58684c11, $c1611dab,
  552.    $b6662d3d, $76dc4190, $01db7106, $98d220bc, $efd5102a, $71b18589, $06b6b51f,
  553.    $9fbfe4a5, $e8b8d433, $7807c9a2, $0f00f934, $9609a88e, $e10e9818, $7f6a0dbb,
  554.    $086d3d2d, $91646c97, $e6635c01, $6b6b51f4, $1c6c6162, $856530d8, $f262004e,
  555.    $6c0695ed, $1b01a57b, $8208f4c1, $f50fc457, $65b0d9c6, $12b7e950, $8bbeb8ea,
  556.    $fcb9887c, $62dd1ddf, $15da2d49, $8cd37cf3, $fbd44c65, $4db26158, $3ab551ce,
  557.    $a3bc0074, $d4bb30e2, $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb, $4369e96a,
  558.    $346ed9fc, $ad678846, $da60b8d0, $44042d73, $33031de5, $aa0a4c5f, $dd0d7cc9,
  559.    $5005713c, $270241aa, $be0b1010, $c90c2086, $5768b525, $206f85b3, $b966d409,
  560.    $ce61e49f, $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4, $59b33d17, $2eb40d81,
  561.    $b7bd5c3b, $c0ba6cad, $edb88320, $9abfb3b6, $03b6e20c, $74b1d29a, $ead54739,
  562.    $9dd277af, $04db2615, $73dc1683, $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
  563.    $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1, $f00f9344, $8708a3d2, $1e01f268,
  564.    $6906c2fe, $f762575d, $806567cb, $196c3671, $6e6b06e7, $fed41b76, $89d32be0,
  565.    $10da7a5a, $67dd4acc, $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5, $d6d6a3e8,
  566.    $a1d1937e, $38d8c2c4, $4fdff252, $d1bb67f1, $a6bc5767, $3fb506dd, $48b2364b,
  567.    $d80d2bda, $af0a1b4c, $36034af6, $41047a60, $df60efc3, $a867df55, $316e8eef,
  568.    $4669be79, $cb61b38c, $bc66831a, $256fd2a0, $5268e236, $cc0c7795, $bb0b4703,
  569.    $220216b9, $5505262f, $c5ba3bbe, $b2bd0b28, $2bb45a92, $5cb36a04, $c2d7ffa7,
  570.    $b5d0cf31, $2cd99e8b, $5bdeae1d, $9b64c2b0, $ec63f226, $756aa39c, $026d930a,
  571.    $9c0906a9, $eb0e363f, $72076785, $05005713, $95bf4a82, $e2b87a14, $7bb12bae,
  572.    $0cb61b38, $92d28e9b, $e5d5be0d, $7cdcefb7, $0bdbdf21, $86d3d2d4, $f1d4e242,
  573.    $68ddb3f8, $1fda836e, $81be16cd, $f6b9265b, $6fb077e1, $18b74777, $88085ae6,
  574.    $ff0f6a70, $66063bca, $11010b5c, $8f659eff, $f862ae69, $616bffd3, $166ccf45,
  575.    $a00ae278, $d70dd2ee, $4e048354, $3903b3c2, $a7672661, $d06016f7, $4969474d,
  576.    $3e6e77db, $aed16a4a, $d9d65adc, $40df0b66, $37d83bf0, $a9bcae53, $debb9ec5,
  577.    $47b2cf7f, $30b5ffe9, $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6, $bad03605,
  578.    $cdd70693, $54de5729, $23d967bf, $b3667a2e, $c4614ab8, $5d681b02, $2a6f2b94,
  579.    $b40bbe37, $c30c8ea1, $5a05df1b, $2d02ef8d
  580.   );
  581.  
  582.  
  583.   function updc32(octet: byte; crc: longint) : longint;
  584.   begin { updc32 }
  585.     updc32 := crc_32_tab[byte(crc xor longint(octet))] xor (
  586.       (crc shr 8) and $00ffffff
  587.     )
  588.   end;
  589.  
  590.  
  591.  
  592.   function z_openfile(var f: file; pathname: string): boolean;
  593.   begin {$i-}
  594.     assign(f,pathname); reset(f,1); z_openfile := (ioresult = 0)
  595.   end; {$i+}
  596.  
  597.  
  598.  
  599.   function z_makefile(var f: file; pathname: string): boolean;
  600.   begin {$I-}
  601.      assign(f,pathname);
  602.      rewrite(f,1);
  603.      z_makefile := (ioresult = 0)
  604.   end; {$I+}
  605.  
  606.  
  607.  
  608.   procedure z_closefile(var f: file);
  609.   begin {$I-}
  610.     close(f); if (ioresult <> 0) then { ignore this error }
  611.   end; {$I+}
  612.  
  613.  
  614.  
  615.   function z_seekfile(var f: file; fpos: longint): boolean;
  616.   begin {$I-}
  617.     seek(f,fpos); z_seekfile := (ioresult = 0)
  618.   end; {$I+}
  619.   
  620.  
  621.   function z_writefile(var f: file; var buff; bytes: word): boolean;
  622.   begin {$I-}
  623.     blockwrite(f,buff,bytes); z_writefile := (ioresult = 0)
  624.   end; {$I+}
  625.   
  626.  
  627.   function z_readfile(var f: file; var buff; btoread: word; var bread: word): boolean;
  628.   begin {$I-}
  629.     blockread(f,buff,btoread,bread); z_readfile := (ioresult = 0)
  630.   end; {$I+}
  631.  
  632.   
  633.   function z_findfile(
  634.     pathname: string; var name: string; var size, time: longint
  635.   ): boolean;
  636.   var sr: searchrec;
  637.   begin {$I-}
  638.     findfirst(pathname+'*', anyfile, sr);
  639.     if (doserror <> 0) or (ioresult <> 0) then begin
  640.       z_findfile := false; exit
  641.     end;
  642.     name := sr.name; size := sr.size; time := sr.time; z_findfile := true
  643.   end; {$I+}
  644.  
  645.  
  646.  
  647.   procedure z_setftime(var f: file; time: longint);
  648.   begin {$I-}
  649.     setftime(f,time); if (ioresult <> 0) then {null}
  650.   end; {$I+}
  651.   
  652.   
  653.  
  654.   function z_settimer: longint;
  655.   var
  656.      l: longint;
  657.      h,m,s,x: word;
  658.  
  659.   begin
  660.     gettime(h,m,s,x);
  661.     l := longint(h) * 3600; inc(l, longint(m) * 60); inc(l, longint(s));
  662.     z_settimer := l
  663.   end;
  664.  
  665.  
  666.  
  667.   const
  668.     c1970 = 2440588;
  669.     d0    =    1461;
  670.     d1    =  146097;
  671.     d2    = 1721119;
  672.  
  673.  
  674.  
  675.   procedure gregoriantojuliandn(
  676.     year, month, day : integer; var juliandn : longint
  677.   );
  678.   
  679.   var
  680.     century,
  681.     xyear    : longint;
  682.  
  683.   begin {gregoriantojuliandn}
  684.     if month <= 2 then begin dec(year); inc(month, 12) end;
  685.     dec(month, 3); century := year div 100; xyear := year mod 100;
  686.     century := (century * d1) shr 2; xyear := (xyear * d0) shr 2;
  687.     juliandn := ((((month * 153) + 2) div 5) + day) + d2 + xyear + century;
  688.   end; {gregoriantojuliandn}
  689.  
  690.  
  691.   
  692.   procedure juliandntogregorian(
  693.     juliandn : longint; var year, month, day : integer
  694.   );
  695.   
  696.   var
  697.     temp,
  698.     xyear   : longint;
  699.     yyear,
  700.     ymonth,
  701.     yday    : integer;
  702.  
  703.   begin {juliandntogregorian}
  704.     temp := (((juliandn - d2) shl 2) - 1); xyear := (temp mod d1) or 3;
  705.     juliandn := temp div d1; yyear := (xyear div d0);
  706.     temp := ((((xyear mod d0) + 4) shr 2) * 5) - 3;
  707.     ymonth := temp div 153;
  708.     if ymonth >= 10 then begin inc(yyear); dec(ymonth, 12) end;
  709.     ymonth := ymonth + 3; yday := temp mod 153; yday := (yday + 5) div 5;
  710.     year := yyear + (juliandn * 100); month := ymonth; day := yday;
  711.   end; {juliandntogregorian}
  712.  
  713.  
  714.  
  715.   function z_tounixdate(fdate: longint): string;
  716.   var
  717.      dt: datetime;
  718.      secspast, datenum, dayspast: longint;
  719.      s: string;
  720.  
  721.   begin
  722.      unpacktime(fdate,dt);
  723.      gregoriantojuliandn(dt.year,dt.month,dt.day,datenum);
  724.      dayspast := datenum - c1970;
  725.      secspast := dayspast * 86400;
  726.      secspast := secspast + dt.hour * 3600 + dt.min * 60 + dt.sec;
  727.      s := '';
  728.      while (secspast <> 0) and (length(s) < 255) do begin
  729.        s := chr((secspast and 7) + $30) + s;
  730.        secspast := (secspast shr 3)
  731.      end;
  732.      s := '0' + s;
  733.      z_tounixdate := s
  734.   end;
  735.  
  736.  
  737.  
  738.   function z_fromunixdate(s: string): longint;
  739.   var
  740.      dt: datetime;
  741.      secspast, datenum: longint;
  742.      n: word;
  743.   begin
  744.      secspast := longint(0);
  745.      for n := 1 to length(s) do
  746.         secspast := (secspast shl 3) + ord(s[n]) - $30;
  747.      datenum := (secspast div 86400) + c1970;
  748.      juliandntogregorian(datenum,integer(dt.year),integer(dt.month),integer(dt.day));
  749.      secspast := secspast mod 86400;
  750.      dt.hour := secspast div 3600;
  751.      secspast := secspast mod 3600;
  752.      dt.min := secspast div 60;
  753.      dt.sec := secspast mod 60;
  754.      packtime(dt,secspast);
  755.      z_fromunixdate := secspast
  756.   end;
  757.  
  758.  
  759.  
  760.  
  761.   function rtos(r: real; width, decimals: word): string;
  762.   var s: string;
  763.   begin
  764.     if r <> 0 then str(r: width: decimals, s) else s := '';
  765.     if (ioresult <> 0) then s := '' else
  766.     while (length(s) > 0) and (s[1] = ' ') do delete(s,1,1);
  767.     rtos := s
  768.   end;
  769.  
  770.  
  771.  
  772.  
  773.   function itos(r: longint; width: word): string;
  774.   var s: string;
  775.   begin
  776.     str(r: width, s);
  777.     if (ioresult <> 0) then s := '' else
  778.       while (length(s) > 0) and (s[1] = ' ') do delete(s,1,1);
  779.     itos := s
  780.   end;
  781.  
  782.   
  783.  
  784.   function pitos(r: longint; width: word): string;
  785.   var
  786.     s : string;
  787.     i :   byte;
  788.  
  789.   begin
  790.     str(r: width, s);
  791.     if (ioresult <> 0) then s := '' else begin
  792.       i := 1; while (i < length(s)) and (s[i] = ' ') do s[i] := '0'; inc(i);
  793.     end;
  794.     pitos := s;
  795.   end;
  796.  
  797.  
  798.  
  799. const
  800.   fore  : byte = lightgray;
  801.   back  : byte = black;
  802.   bfore : byte = black;
  803.   bback : byte = green;
  804.  
  805. var
  806.   x1, x2, x3, x4,
  807.   y1, y2, oldx, oldy : byte;
  808.  
  809.  
  810.  
  811.  
  812.   {====================================}
  813.   procedure z_openwindow(title, action: string);
  814.   var
  815.      p, q     : pointer;
  816.      n, pads, 
  817.      bytes    :    word;
  818.      st       :  string;
  819.  
  820.   begin
  821.     x1 := 10;
  822.     x2 := x1 + 61;
  823.     x3 := x1 + 17;
  824.     x4 := x1 + 36;
  825.     y1 := 4;
  826.     y2 := y1 + 17;
  827.     oldx := wherex; oldy := wherey;
  828.     __bandwin(false, x1, y1, x2, y2, bfore, bback, sh_default, bt_double);
  829.     if usefossil then st := '(USING FOSSIL)' else st := '(DIRECT RS232)';
  830.     __betwscn(x1, x2, y1, bfore, bback,'[ ' + action + ' ' + title + ' ' + st + ' ]');
  831.     __write(x1 + 1, y1 + 01, bfore, bback, ' File name    :');
  832.     __write(x1 + 1, y1 + 02, bfore, bback, ' File size    :');
  833.     __write(x1 + 1, y1 + 03, bfore, bback, ' File blocks  :');
  834.     __write(x1 + 1, y1 + 04, bfore, bback, ' Block check  :');
  835.     __write(x1 + 1, y1 + 05, bfore, bback, ' Transfertime :');
  836.     __write(x1 + 1, y1 + 06, bfore, bback, ' Current BYTE :');
  837.     __write(x1 + 1, y1 + 07, bfore, bback, ' Total bytes  :');
  838.     __write(x1 + 1, y1 + 08, bfore, bback, ' Current BLCK :');
  839.     __write(x1 + 1, y1 + 09, bfore, bback, ' Total blocks :');
  840.     __write(x1 + 1, y1 + 10, bfore, bback, ' Block size   :');
  841.     __write(x1 + 1, y1 + 11, bfore, bback, ' Error count  :');
  842.     __write(x1 + 1, y1 + 12, bfore, bback, ' Last frame   :');
  843.     __write(x1 + 1, y1 + 13, bfore, bback, ' Chrs per sec.:');
  844.     __write(x1 + 1, y1 + 14, bfore, bback, ' Efficiency   :');
  845.     {---}
  846.     __write(x1 + 2, y2 - 1,  bfore, bback, __rep(x4-x1-3,'░'));
  847.     __vert(x4, y1 + 1, bfore, bback, __rep(y2 - y1 - 1, '│'));
  848.   end;
  849.   
  850.   
  851.  
  852.  
  853.   procedure z_showname(filename: string);
  854.   begin
  855.     if (length(filename) > 14) then filename[0] := #14;
  856.     __write(x3, y1 + 1, bfore, bback, filename);
  857.   end;
  858.  
  859.  
  860.   procedure z_showsize(l: longint);
  861.   begin
  862.     __write(x3, y1 + 02, bfore, bback,
  863.       __pntstr(l) + ' ' + itos(l div 1024, 5) + 'K'
  864.     );
  865.     if (l mod 128 <> 0) then l := (l div 128) + 1 else l := (l div 128);
  866.     __write(x3, y1 + 03, bfore, bback, __pntstr(l));
  867.   end;
  868.  
  869.  
  870.  
  871.   procedure z_showcheck(is32: boolean);
  872.   begin
  873.     if (is32) then __write(
  874.       x3, y1 + 04, bfore, bback, 'CRC32'
  875.     ) else __write(
  876.       x3, y1 + 04, bfore, bback, 'CRC16'
  877.     )
  878.   end;
  879.  
  880.  
  881.  
  882.   function getxfrtime(fsize, zbaud: longint): string;
  883.   var
  884.     hours,
  885.     mins,
  886.     secs : byte;
  887.     bits : real;
  888.  
  889.   begin
  890.     bits := ((fsize * 10.0) / zbaud) / 60;      {              all seconds }
  891.     secs := round((bits - trunc(bits)) * 60);   {             seconds only }
  892.     mins := trunc(bits);                        { cut seconds from minutes }
  893.     hours := 0;
  894.     if mins > 60 then begin hours := mins div 60; mins := mins div 60 end;
  895.     getxfrtime := pitos(hours, 2) + ':' + pitos(mins, 2) + '.' + pitos(secs, 2)
  896.   end;
  897.  
  898.  
  899.   procedure z_showtransfertime(fsize, zbaud: longint);
  900.   begin
  901.     if zbaud = 0 then __write(
  902.       x3, y1 + 05, bfore, bback, '0 min.'
  903.     ) else __write(x3, y1 + 05, bfore, bback, getxfrtime(fsize, zbaud));
  904.   end;
  905.  
  906.  
  907.  
  908.   procedure z_showtransfertimesofar(fsize, fdone, zbaud: longint);
  909.   var
  910.     hours,
  911.     mins,
  912.     secs : byte;
  913.     bits : real;
  914.  
  915.   begin
  916.     if zbaud = 0 then __write(
  917.       x3, y1 + 05, bfore, bback, '0 min.'
  918.     ) else begin
  919.       bits := ((fdone * 10.0) / zbaud) / 60;      {              all seconds }
  920.       secs := round((bits - trunc(bits)) * 60);   {             seconds only }
  921.       mins := trunc(bits);                        { cut seconds from minutes }
  922.       hours := 0;
  923.       if mins > 60 then begin hours := mins div 60; mins := mins div 60 end;
  924.       
  925.       __write(x1+2, y1 + 15, bfore, bback, 'Xfr time: ' +
  926.         pitos(hours, 2) + ':' + pitos(mins, 2) + '.' + pitos(secs, 2) + '  '
  927.       );
  928.  
  929.       bits := (((fsize-fdone) * 10.0) / zbaud) / 60; { all seconds yet to do }
  930.       secs := round((bits - trunc(bits)) * 60);   {             seconds only }
  931.       mins := trunc(bits);                        { cut seconds from minutes }
  932.       hours := 0;
  933.       if mins > 60 then begin hours := mins div 60; mins := mins div 60 end;
  934.       __write(x1+24, y1 + 15, bfore, bback, '(' +
  935.         pitos(hours, 2) + ':' + pitos(mins, 2) + '.' + pitos(secs, 2) + ')  '
  936.       );
  937.  
  938.     end;
  939.   end;
  940.  
  941.   
  942.  
  943.   procedure z_message(s: string);
  944.   begin
  945.     __attrib(x4+2, y2-3, x2-1, y2-1, bfore, bback);
  946.     __copyscn(x4+2, y1+2, x2-1, y2-1, x4+2, y1+1);
  947.     __write(x4+2, y2-1, bfore, bback, __rep(x2-x4-2, ' '));
  948.     if (copy(s, 1, 3) = 'ERR') or (copy(s, 2, 3) = 'ERR') then
  949.       __write(x4+2, y2-1, 14, 1, copy(s, 1, x2-x4-2)) else
  950.       __write(x4+2, y2-1, 15, bback, copy(s, 1, x2-x4-2));
  951.   end;
  952.  
  953.   
  954.   procedure z_frame(n: integer);
  955.   var st: string;
  956.   begin
  957.     if (n < -3) or (n > 20) then n := 20;
  958.     case n of
  959.        -3 : st := 'ZNOCARRIER';
  960.        -2 : st := 'ZTIMEOUT  ';
  961.        -1 : st := 'ZERROR    ';
  962.        0  : st := 'ZRQINIT   ';
  963.        1  : st := 'ZRINIT    ';
  964.        2  : st := 'ZSINIT    ';
  965.        3  : st := 'ZACK      ';
  966.        4  : st := 'ZFILE     ';
  967.        5  : st := 'ZSKIP     ';
  968.        6  : st := 'ZNAK      ';
  969.        7  : st := 'ZABORT    ';
  970.        8  : st := 'ZFIN      ';
  971.        9  : st := 'ZRPOS     ';
  972.        10 : st := 'ZDATA     ';
  973.        11 : st := 'ZEOF      ';
  974.        12 : st := 'ZFERR     ';
  975.        13 : st := 'ZCRC      ';
  976.        14 : st := 'ZCHALLENGE';
  977.        15 : st := 'ZCOMPL    ';
  978.        16 : st := 'ZCAN      ';
  979.        17 : st := 'ZFREECNT  ';
  980.        18 : st := 'ZCOMMAND  ';
  981.        19 : st := 'ZSTDERR   ';
  982.        20 : st := 'ZUNKNOWN  '
  983.     end;
  984.     __write(x3, y1+12, bfore, bback, st);
  985.   end;
  986.  
  987.  
  988.  
  989.   {@ UPDATE ALL "WICHTIGE" INFORMATION }
  990.   procedure z_showloc(l: longint);
  991.   var
  992.     r        :    real;
  993.     tmpl, tt : longint;
  994.  
  995.   begin
  996.     if fsize > 0 then r := (l / fsize) * (x4-x1-3);
  997.     if fsize > 0 then __write(x1 +2, y2 -1, bfore, bback, __rep(trunc(r), '█'));
  998.     z_showtransfertimesofar(fsize, l, zbaud);
  999.     if (l / fsize) * 100 >= 15 then __write(x1 +3, y2 -1, bback, bfore,
  1000.       itos(trunc((l / fsize) * 100), 3) + '%'
  1001.     );
  1002.     __write(x3, y1 + 06, bfore, bback,
  1003.       __pntstr(l) + ' ' + itos(l div 1024, 5) + 'K'
  1004.     );
  1005.     __write(x3, y1 + 07, bfore, bback,
  1006.       __pntstr(totalbytes) + ' ' + itos(totalbytes div 1024, 5) + 'K'
  1007.     );
  1008.  
  1009.     if (z_settimer - ztime) <> 0 then zcps := l div (z_settimer - ztime);
  1010.     if (l mod 128 <> 0) then l := (l div 128) + 1 else l := (l div 128);
  1011.     if (totalbytes mod 128 <> 0) then tt := (totalbytes div 128) + 1 else
  1012.       tt := (totalbytes div 128);
  1013.     __write(x3, y1+08, bfore, bback, __pntstr(l) + '  ');
  1014.     __write(x3, y1+09, bfore, bback, __pntstr(tt) + '  ');
  1015.     __write(x3, y1 + 13, bfore, bback, itos(zcps, 5) + ' cps  ');
  1016.     if zbaud > 0 then __write(x3, y1 + 14, bfore, bback, 
  1017.       itos(trunc(((zcps * 10) / zbaud) * 100), 3) + ' % '
  1018.     );
  1019.     tmpl := abs(l - oldl) * 128;
  1020.     __write(x3, y1 + 10, bfore, bback, itos(tmpl, 5) + '       ');
  1021.     oldl := l;
  1022.   end;
  1023.  
  1024.  
  1025.  
  1026.   procedure z_errors(w: word);
  1027.   begin
  1028.     __write(x3, y1+11, bfore, bback, itos(w,14));
  1029.   end;
  1030.   
  1031.  
  1032.  
  1033.  
  1034.  
  1035. (***************************************************)
  1036. (* all zmodem direction-independent routines       *)
  1037. (***************************************************)
  1038.  
  1039.   function z_filecrc32(var f: file): longint;
  1040.   var
  1041.      fbuf     : buftype;
  1042.      crc      : longint;
  1043.      bread, n : integer;
  1044.  
  1045.   begin {$I-}
  1046.     crc := $ffffffff;
  1047.     seek(f,0);
  1048.     if (ioresult <> 0) then {null};
  1049.     repeat
  1050.       blockread(f,fbuf,zbufsize,bread);
  1051.       for n := 0 to (bread - 1) do crc := updc32(fbuf[n],crc)
  1052.     until (bread < zbufsize) or (ioresult <> 0);
  1053.     seek(f,0);
  1054.     if (ioresult <> 0) then {null};
  1055.     z_filecrc32 := crc
  1056.   end; {$I+}
  1057.  
  1058.  
  1059.  
  1060.   
  1061.   function z_getbyte(tenths: integer): integer;
  1062.   (* reads a byte from the modem - returns rcdo if *)
  1063.   (* no carrier, or ztimeout if nothing received   *)
  1064.   (* within 'tenths' of a second.                  *)
  1065.   var
  1066.      n: integer;
  1067.  
  1068.   begin
  1069.     repeat
  1070.       if (not z_carrier) then begin
  1071.         z_getbyte := rcdo; { nobody to talk to } exit
  1072.       end;
  1073.       if (z_charavail) then begin
  1074.         z_getbyte := z_receivebyte; { got character } exit
  1075.       end;
  1076.       dec(tenths);              { dec. the count    }
  1077.       delay(100)                { pause 1/10th sec. }
  1078.     until (tenths <= 0);
  1079.     z_getbyte := ztimeout        { timed out }
  1080.   end;
  1081.  
  1082.  
  1083.  
  1084.  
  1085.   function z_qk_read: integer;
  1086.   (* just like z_getbyte, but timeout value is in *)
  1087.   (* global var rxtimeout.                        *)
  1088.   begin
  1089.      z_qk_read := z_getbyte(rxtimeout)
  1090.   end;
  1091.  
  1092.  
  1093.  
  1094.  
  1095.   function z_timedread: integer;
  1096.   (* a z_qk_read, that strips parity and *)
  1097.   (* ignores xon/xoff characters.        *)
  1098.   var
  1099.     done: boolean;
  1100.     c: integer;
  1101.  
  1102.   begin
  1103.     done := false;
  1104.     repeat
  1105.       c := z_qk_read and $ff7f                { strip parity }
  1106.     until (c < 0) or (not (lo(c) in [17,19])); { wait for other than xon/xoff }
  1107.     z_timedread := c
  1108.   end;
  1109.  
  1110.  
  1111.  
  1112.  
  1113.   procedure z_sendcan;
  1114.   (* send a zmodem cancel sequence to the other guy *)
  1115.   (* 8 cans and 8 backspaces                        *)
  1116.   var
  1117.     n: byte;
  1118.   begin
  1119.     z_clearoutbound; { spare them the junk }
  1120.     for n := 1 to 8 do begin
  1121.       z_sendbyte(can);
  1122.       delay(100)     { the pause seems to make reception of the sequence }
  1123.     end;             { more reliable                                     }
  1124.     for n := 1 to 8 do z_sendbyte(8)
  1125.   end;
  1126.  
  1127.  
  1128.  
  1129.  
  1130.   procedure z_putstring(var p: buftype);
  1131.   (* outputs an ascii-z type string (null terminated) *)
  1132.   (* processes meta characters 221 (send break) and   *)
  1133.   (* 222 (2 second delay).                            *)
  1134.   var n: integer;
  1135.   begin
  1136.     n := 0;
  1137.     while (n < zbufsize) and (p[n] <> 0) do begin
  1138.       case p[n] of
  1139.         221 : z_sendbreak;
  1140.         222 : delay(2000)
  1141.         else z_sendbyte(p[n])
  1142.       end;
  1143.       inc(n)
  1144.     end
  1145.   end;
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.   procedure z_puthex(b: byte);
  1152.   (* output a byte as two hex digits (in ascii) *)
  1153.   (* uses lower case to avoid confusion with    *)
  1154.   (* escaped control characters.                *)
  1155.   const hex: array[0..15] of char = '0123456789abcdef';
  1156.   begin
  1157.     z_sendbyte(ord(hex[b shr 4]));  { high nybble }
  1158.     z_sendbyte(ord(hex[b and $0f])) { low nybble  }
  1159.   end;
  1160.  
  1161.  
  1162.  
  1163.  
  1164.   procedure z_sendhexheader(htype: byte; var hdr: hdrtype);
  1165.   (* sends a zmodem hex type header *)
  1166.   var
  1167.     crc: word;
  1168.     n, i: integer;
  1169.  
  1170.   begin
  1171.     z_sendbyte(zpad);                  { '*' }
  1172.     z_sendbyte(zpad);                  { '*' }
  1173.     z_sendbyte(zdle);                  { 24  }
  1174.     z_sendbyte(zhex);                  { 'B' }
  1175.     z_puthex(htype);
  1176.     crc := updcrc(htype,0);
  1177.     for n := 0 to 3 do begin z_puthex(hdr[n]); crc := updcrc(hdr[n],crc) end;
  1178.     crc := updcrc(0,crc); crc := updcrc(0,crc);
  1179.     z_puthex(lo(crc shr 8)); z_puthex(lo(crc));
  1180.     z_sendbyte(13);                    { make it readable to the other end }
  1181.     z_sendbyte(10);                    { just in case                      }
  1182.     if (htype <> zfin) and (htype <> zack) then z_sendbyte(17);
  1183.                                        { prophylactic xon to assure flow   }
  1184.     if (not z_carrier) then z_clearoutbound
  1185.   end;
  1186.  
  1187.  
  1188.  
  1189.  
  1190.   function z_pulllongfromheader(var hdr: hdrtype): longint;
  1191.   (* stuffs a longint into a header variable - n.b. - bytes are reversed! *)
  1192.   var l: longint;
  1193.   begin
  1194.     l := hdr[zp3];               { hard coded for efficiency }
  1195.     l := (l shl 8) or hdr[zp2];
  1196.     l := (l shl 8) or hdr[zp1];
  1197.     l := (l shl 8) or hdr[zp0];
  1198.     z_pulllongfromheader := l
  1199.   end;
  1200.  
  1201.  
  1202.  
  1203.  
  1204.   procedure z_putlongintoheader(l: longint); (* reverse of above *)
  1205.   begin
  1206.     txhdr[zp0] := byte(l);
  1207.     txhdr[zp1] := byte(l shr 8);
  1208.     txhdr[zp2] := byte(l shr 16);
  1209.     txhdr[zp3] := byte(l shr 24)
  1210.   end;
  1211.  
  1212.  
  1213.  
  1214.  
  1215.   function z_getzdl: integer;
  1216.   (* gets a byte and processes for zmodem escaping or cancel sequence *)
  1217.   var
  1218.     c, d: integer;
  1219.  
  1220.   begin
  1221.     if (not z_carrier) then begin z_getzdl := rcdo; exit end;
  1222.     c := z_qk_read;
  1223.     if (c <> zdle) then begin z_getzdl := c; exit end;   {got zdle or 1st can}
  1224.     c := z_qk_read;
  1225.     if (c = can) then begin {got 2nd can}
  1226.       c := z_qk_read;
  1227.       if (c = can) then {got 3rd can} begin
  1228.         c := z_qk_read;
  1229.         if (c = can) then {got 4th can} c := z_qk_read
  1230.       end
  1231.     end;
  1232.     { flags set in high byte }
  1233.     case c of
  1234.       can: z_getzdl := gotcan; {got 5th can}
  1235.       zcrce,                   {got a frame end marker}
  1236.       zcrcg,
  1237.       zcrcq,
  1238.       zcrcw: z_getzdl := (c or gotor);
  1239.       zrub0: z_getzdl := $007f; {got an ascii delete}
  1240.       zrub1: z_getzdl := $00ff  {any parity         }
  1241.       else begin
  1242.         if (c < 0) then z_getzdl := c else if (
  1243.           (c and $60) = $40
  1244.         ) then z_getzdl := c xor $40 else {make sure it was a valid escape}
  1245.           z_getzdl := zerror
  1246.       end
  1247.     end { case }
  1248.   end;
  1249.  
  1250.  
  1251.  
  1252.   function z_gethex: integer;
  1253.   (* get a byte that has been received as two ascii hex digits *)
  1254.   var
  1255.     c, n: integer;
  1256.  
  1257.   begin
  1258.     n := z_timedread;
  1259.     if (n < 0) then begin z_gethex := n; exit end;
  1260.     n := n - $30;                     {build the high nybble}
  1261.     if (n > 9) then n := n - 39;
  1262.     if (n and $fff0 <> 0) then begin z_gethex := zerror; exit end;
  1263.     c := z_timedread;
  1264.     if (c < 0) then begin z_gethex := c; exit end;
  1265.     c := c - $30;                     {now the low nybble}
  1266.     if (c > 9) then c := c - 39;
  1267.     if (c and $fff0 <> 0) then begin z_gethex := zerror; exit end;
  1268.     z_gethex := (n shl 4) or c        {insert tab 'A' in slot 'B'...}
  1269.   end;
  1270.  
  1271.  
  1272.  
  1273.   
  1274.   function z_gethexheader(var hdr: hdrtype): integer;
  1275.   (* receives a zmodem hex type header *)
  1276.   var
  1277.     crc: word;
  1278.     c, n: integer;
  1279.  
  1280.   begin
  1281.     c := z_gethex;
  1282.     if (c < 0) then begin
  1283.       z_gethexheader := c;
  1284.       exit
  1285.     end;
  1286.     rxtype := c;                        {get the type of header}
  1287.     crc := updcrc(rxtype,0);
  1288.     for n := 0 to 3 do begin            {get the 4 bytes}
  1289.       c := z_gethex;
  1290.       if (c < 0) then begin
  1291.         z_gethexheader := c;
  1292.         exit
  1293.       end;
  1294.       hdr[n] := lo(c);
  1295.       crc := updcrc(lo(c),crc)
  1296.     end;
  1297.     c := z_gethex;
  1298.     if (c < 0) then begin
  1299.       z_gethexheader := c;
  1300.       exit
  1301.     end;
  1302.     crc := updcrc(lo(c),crc);
  1303.     c := z_gethex;
  1304.     if (c < 0) then begin
  1305.       z_gethexheader := c;
  1306.       exit
  1307.     end;
  1308.     crc := updcrc(lo(c),crc);             {check the crc}
  1309.     if (crc <> 0) then begin
  1310.       inc(zerrors);
  1311.       z_errors(zerrors);
  1312.       z_gethexheader := zerror;
  1313.       exit
  1314.     end;
  1315.     if (z_getbyte(1) = 13) then           {throw away cr/lf}
  1316.       c := z_getbyte(1);
  1317.     z_gethexheader := rxtype
  1318.   end;
  1319.  
  1320.  
  1321.  
  1322.   function z_getbinaryheader(var hdr: hdrtype): integer;
  1323.   (* same as above, but binary with 16 bit crc *)
  1324.   var
  1325.     crc: word;
  1326.     c, n: integer;
  1327.  
  1328.   begin
  1329.     c := z_getzdl;
  1330.     if (c < 0) then begin
  1331.       z_getbinaryheader := c;
  1332.       exit
  1333.     end;
  1334.     rxtype := c;
  1335.     crc := updcrc(rxtype,0);
  1336.     for n := 0 to 3 do begin
  1337.       c := z_getzdl;
  1338.       if (hi(c) <> 0) then begin
  1339.         z_getbinaryheader := c;
  1340.         exit
  1341.       end;
  1342.       hdr[n] := lo(c);
  1343.       crc := updcrc(lo(c),crc)
  1344.     end;
  1345.     c := z_getzdl;
  1346.     if (hi(c) <> 0) then begin
  1347.       z_getbinaryheader := c;
  1348.       exit
  1349.     end;
  1350.     crc := updcrc(lo(c),crc);
  1351.     c := z_getzdl;
  1352.     if (hi(c) <> 0) then begin
  1353.       z_getbinaryheader := c;
  1354.       exit
  1355.     end;
  1356.     crc := updcrc(lo(c),crc);
  1357.     if (crc <> 0) then begin
  1358.       inc(zerrors);
  1359.       z_errors(zerrors);
  1360.       exit
  1361.     end;
  1362.     z_getbinaryheader := rxtype
  1363.   end;
  1364.  
  1365.  
  1366.  
  1367.   function z_getbinaryhead32(var hdr: hdrtype): integer;
  1368.   (* same as above but with 32 bit crc *)
  1369.   var
  1370.     crc: longint;
  1371.     c, n: integer;
  1372.   
  1373.   begin
  1374.     c := z_getzdl;
  1375.     if (c < 0) then begin
  1376.       z_getbinaryhead32 := c;
  1377.       exit
  1378.     end;
  1379.     rxtype := c;
  1380.     crc := updc32(rxtype,$ffffffff);
  1381.     for n := 0 to 3 do begin
  1382.       c := z_getzdl;
  1383.       if (hi(c) <> 0) then begin
  1384.         z_getbinaryhead32 := c;
  1385.         exit
  1386.       end;
  1387.       hdr[n] := lo(c);
  1388.       crc := updc32(lo(c),crc)
  1389.     end;
  1390.     for n := 0 to 3 do begin
  1391.       c := z_getzdl;
  1392.       if (hi(c) <> 0) then begin
  1393.         z_getbinaryhead32 := c;
  1394.         exit
  1395.       end;
  1396.       crc := updc32(lo(c),crc)
  1397.     end;
  1398.     if (crc <> $debb20e3) then begin  {this is the polynomial value}
  1399.       inc(zerrors);
  1400.       z_errors(zerrors);
  1401.       z_getbinaryhead32 := zerror;
  1402.       exit
  1403.     end;
  1404.     z_getbinaryhead32 := rxtype
  1405.   end;
  1406.   
  1407.   
  1408.  
  1409.  
  1410.   function z_getheader(var hdr: hdrtype): integer;
  1411.   (* use this routine to get a header - it will figure out  *)
  1412.   (* what type it is getting (hex, bin16 or bin32) and call *)
  1413.   (* the appropriate routine.                               *)
  1414.   label
  1415.     gotcan, again, agn2, splat, done;  {sorry, but it's actually eisier to}
  1416.   var                                  {follow, and lots more efficient   }
  1417.     c, n, cancount: integer;           {this way...                       }
  1418.  
  1419.   begin
  1420.     n := zbaud * 2;                    {a guess at the # of garbage characters}
  1421.     cancount := 5;                     {to expect.                            }
  1422.     usecrc32 := false;                 {assume 16 bit until proven otherwise  }
  1423. again:
  1424.     if (keypressed) then if (readkey = #27) then begin { operator panic }
  1425.       z_sendcan;                             {tell the other end,   }
  1426.       z_message('Cancelled from keyboard');  {the operator,         }
  1427.       z_getheader := zcan;                   {and the rest of the   }
  1428.       exit                                   {routines to forget it.}
  1429.     end;
  1430.     rxframeind := 0;
  1431.     rxtype := 0;
  1432.     c := z_timedread;
  1433.     case c of
  1434.       zpad: {we want this! - all headers begin with '*'.} ;
  1435.       rcdo,
  1436.       ztimeout: goto done;
  1437.  
  1438.       can: begin
  1439. gotcan:
  1440.         dec(cancount);
  1441.         if (cancount < 0) then begin
  1442.           c := zcan;
  1443.           goto done
  1444.         end;
  1445.         c := z_getbyte(1);
  1446.         case c of
  1447.           ztimeout: goto again;
  1448.           zcrcw: begin
  1449.             c := zerror;
  1450.             goto done
  1451.           end;
  1452.           rcdo: goto done;
  1453.           can: begin
  1454.             dec(cancount);
  1455.             if (cancount < 0) then begin
  1456.               c := zcan;
  1457.               goto done
  1458.             end;
  1459.             goto again
  1460.           end
  1461.           else {fallthru}
  1462.         end {case}
  1463.       end {can} else begin
  1464. agn2: 
  1465.         dec(n);
  1466.         if (n < 0) then begin
  1467.           inc(zerrors);
  1468.           z_errors(zerrors);
  1469.           z_message('Header is FUBAR');
  1470.           z_getheader := zerror;
  1471.           exit
  1472.         end;
  1473.         if (c <> can) then
  1474.           cancount := 5;
  1475.         goto again
  1476.       end
  1477.     end;           {only falls thru if zpad - anything else is trash}
  1478.     cancount := 5;
  1479.  
  1480. splat:
  1481.     c := z_timedread;
  1482.     case c of
  1483.       zdle: {this is what we want!} ;
  1484.       zpad: goto splat;   {junk or second '*' of a hex header}
  1485.       rcdo,
  1486.       ztimeout: goto done
  1487.       else goto agn2
  1488.     end; {only falls thru if zdle}
  1489.     c := z_timedread;
  1490.     case c of
  1491.       zbin32: begin
  1492.         rxframeind := zbin32;        {using 32 bit crc}
  1493.         c := z_getbinaryhead32(hdr)
  1494.       end;
  1495.  
  1496.       zbin: begin
  1497.         rxframeind := zbin;            {bin with 16 bit crc}
  1498.         c := z_getbinaryheader(hdr)
  1499.       end;
  1500.  
  1501.       zhex: begin
  1502.         rxframeind := zhex;            {hex}
  1503.         c := z_gethexheader(hdr)
  1504.       end;
  1505.  
  1506.       can: goto gotcan;
  1507.  
  1508.       rcdo,
  1509.       ztimeout: goto done
  1510.  
  1511.       else goto agn2
  1512.     end; {only falls thru if we got zbin, zbin32 or zhex}
  1513.     rxpos := z_pulllongfromheader(hdr);        {set rxpos just in case this}
  1514. done:                                         {header has file position   }
  1515.     z_getheader := c                           {info (i.e.: zrpos, etc.   )}
  1516.   end;
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.  
  1524.  
  1525. (***************************************************)
  1526. (* receive file routines                           *)
  1527. (***************************************************)
  1528.  
  1529. const
  1530.   zattnlen          = 32;  { max length of attention string }
  1531.   lastwritten: byte = 00;
  1532.  
  1533. var
  1534.   t           : longint;
  1535.   rzbatch     : boolean;
  1536.   outfile     :    file;     {this is the file}
  1537.   tryzhdrtype :    byte;
  1538.   rxcount     : integer;
  1539.   filestart   : longint;
  1540.   isbinary, 
  1541.   eofseen     : boolean;
  1542.   zconv       :    byte;
  1543.   zrxpath     :  string;
  1544.  
  1545.  
  1546.  
  1547.   function rz_receiveda32(var buf: buftype; blength: integer): integer;
  1548.   (* get a 32 bit crc data block *)
  1549.   label crcfoo;
  1550.   var
  1551.     c, d, n : integer;
  1552.     crc     : longint;
  1553.     done    : boolean;
  1554.  
  1555.   begin
  1556.     usecrc32 := true;
  1557.     crc := $ffffffff;
  1558.     rxcount := 0;
  1559.     done := false;
  1560.     repeat
  1561.       c := z_getzdl;
  1562.       if (hi(c) <> 0) then begin
  1563. crcfoo: case c of
  1564.           gotcrce,
  1565.           gotcrcg,
  1566.           gotcrcq,
  1567.           gotcrcw: begin
  1568.             d := c;
  1569.             crc := updc32(lo(c),crc);
  1570.             for n := 0 to 3 do begin
  1571.               c := z_getzdl;
  1572.               if (hi(c) <> 0) then goto crcfoo;
  1573.               crc := updc32(lo(c),crc)
  1574.             end;
  1575.             if (crc <> $debb20e3) then begin
  1576.               inc(zerrors);
  1577.               z_errors(zerrors);
  1578.               rz_receiveda32 := zerror
  1579.             end else rz_receiveda32 := d;
  1580.             done := true
  1581.           end;
  1582.  
  1583.           gotcan: begin
  1584.             rz_receiveda32 := zcan;
  1585.             done := true
  1586.           end;
  1587.  
  1588.           ztimeout: begin
  1589.             rz_receiveda32 := c;
  1590.             done := true
  1591.           end;
  1592.  
  1593.           rcdo: begin
  1594.             rz_receiveda32 := c;
  1595.             done := true
  1596.           end else begin
  1597.             z_message('Debris');
  1598.             z_clearinbound;
  1599.             rz_receiveda32 := c;
  1600.             done := true
  1601.           end;
  1602.         end; { case }
  1603.       end; { if }
  1604.       if (not done) then begin
  1605.         dec(blength);
  1606.         if (blength < 0) then begin
  1607.           z_message('Long packet');
  1608.           rz_receiveda32 := zerror;
  1609.           done := true
  1610.         end;
  1611.         buf[integer(rxcount)] := lo(c);
  1612.         inc(rxcount);
  1613.         crc := updc32(lo(c),crc)
  1614.       end
  1615.     until done
  1616.   end;
  1617.   
  1618.  
  1619.  
  1620.  
  1621.   function rz_receivedata(var buf: buftype; blength: integer): integer;
  1622.   (* get a 16 bit crc data block *)
  1623.   label crcfoo;
  1624.   var
  1625.     c, d: integer;
  1626.     crc: word;
  1627.     done: boolean;
  1628.  
  1629.   begin
  1630.     if (rxframeind = zbin32) then begin
  1631.       z_showcheck(true);
  1632.       rz_receivedata := rz_receiveda32(buf,blength);
  1633.       exit
  1634.     end;
  1635.     z_showcheck(false);
  1636.     crc := 0;
  1637.     rxcount := 0;
  1638.     done := false;
  1639.     repeat
  1640.       c := z_getzdl;
  1641.       if (hi(c) <> 0) then begin
  1642. crcfoo: 
  1643.         case c of
  1644.           gotcrce,
  1645.           gotcrcg,
  1646.           gotcrcq,
  1647.           gotcrcw: begin
  1648.             d := c;
  1649.             crc := updcrc(lo(c),crc);
  1650.             c := z_getzdl;
  1651.             if (hi(c) <> 0) then goto crcfoo;
  1652.             crc := updcrc(lo(c),crc);
  1653.             c := z_getzdl;
  1654.             if (hi(c) <> 0) then goto crcfoo;
  1655.             crc := updcrc(lo(c),crc);
  1656.             if (crc <> 0) then begin
  1657.               inc(zerrors);
  1658.               z_errors(zerrors);
  1659.               rz_receivedata := zerror;
  1660.               done := true
  1661.             end;
  1662.             rz_receivedata := d;
  1663.             done := true
  1664.           end;
  1665.           gotcan: begin
  1666.             z_message('Got CANned');
  1667.             rz_receivedata := zcan;
  1668.             done := true
  1669.           end;
  1670.           ztimeout: begin
  1671.             rz_receivedata := c;
  1672.             done := true
  1673.           end;
  1674.           rcdo: begin
  1675.             z_message('Lost carrier');
  1676.             rz_receivedata := c;
  1677.             done := true
  1678.           end else begin
  1679.             z_message('Debris');
  1680.             z_clearinbound;
  1681.             rz_receivedata := c;
  1682.             done := true
  1683.           end
  1684.         end
  1685.       end;
  1686.       if (not done) then begin
  1687.         dec(blength);
  1688.         if (blength < 0) then begin
  1689.           z_message('Long packet');
  1690.           rz_receivedata := zerror;
  1691.           done := true
  1692.         end;
  1693.         buf[integer(rxcount)] := lo(c);
  1694.         inc(rxcount);
  1695.         crc := updcrc(lo(c),crc)
  1696.       end
  1697.     until done
  1698.   end;
  1699.  
  1700.  
  1701.  
  1702.  
  1703.   procedure rz_ackbibi;
  1704.   (* acknowledge the other ends request to terminate cleanly *)
  1705.   var n: integer;
  1706.  
  1707.   begin
  1708.     z_putlongintoheader(rxpos);
  1709.     n := 4;
  1710.     z_clearinbound;
  1711.     repeat
  1712.       z_sendhexheader(zfin,txhdr);
  1713.       case z_getbyte(20) of
  1714.         ztimeout,
  1715.         rcdo: exit;
  1716.         79: begin
  1717.           if (z_getbyte(10) = 79) then {null};
  1718.           z_clearinbound;
  1719.           exit
  1720.         end else z_clearinbound;
  1721.         dec(n)
  1722.       end
  1723.     until (n <= 0)
  1724.   end;
  1725.   
  1726.  
  1727.  
  1728.   function rz_initreceiver: integer;
  1729.   label again;
  1730.  
  1731.   var
  1732.     c, n, errors: integer;
  1733.  
  1734.   begin
  1735.     fillchar(attn,sizeof(attn),0);
  1736.     zerrors := 0;
  1737.     for n := 10 downto 0 do begin
  1738.       if (not z_carrier) then begin
  1739.         z_message('Lost carrier');
  1740.         rz_initreceiver := zerror;
  1741.         exit
  1742.       end;
  1743.       z_putlongintoheader(longint(0));  {full dplx, overlay i/o and crc32}
  1744.       txhdr[zf0] := canfdx or canovio or canfc32 or canbrk;
  1745.       z_sendhexheader(tryzhdrtype,txhdr);
  1746.       if (tryzhdrtype = zskip) then tryzhdrtype := zrinit;
  1747. again:
  1748.       c := z_getheader(rxhdr);
  1749.       z_frame(c);
  1750.       case c of
  1751.         zfile: begin
  1752.           zconv := rxhdr[zf0];
  1753.           tryzhdrtype := zrinit;
  1754.           c := rz_receivedata(secbuf,zbufsize);
  1755.           z_frame(c);
  1756.           if (c = gotcrcw) then begin
  1757.             rz_initreceiver := zfile;
  1758.             exit
  1759.           end;
  1760.           z_sendhexheader(znak,txhdr);
  1761.           goto again
  1762.         end;
  1763.  
  1764.         zsinit: begin
  1765.           c := rz_receivedata(attn,zbufsize);
  1766.           z_frame(c);
  1767.           if (c = gotcrcw) then z_sendhexheader(zack,txhdr) else
  1768.             z_sendhexheader(znak,txhdr);
  1769.           goto again
  1770.         end;
  1771.  
  1772.         zfreecnt: begin
  1773.           z_putlongintoheader(diskfree(0));
  1774.           z_sendhexheader(zack,txhdr);
  1775.           goto again
  1776.         end;
  1777.  
  1778.         zcommand: begin
  1779.           c := rz_receivedata(secbuf,zbufsize);
  1780.           z_frame(c);
  1781.           if (c = gotcrcw) then begin
  1782.             z_putlongintoheader(longint(0));
  1783.             repeat
  1784.               z_sendhexheader(zcompl,txhdr);
  1785.               inc(errors)
  1786.             until (errors > 10) or (z_getheader(rxhdr) = zfin);
  1787.             rz_ackbibi;
  1788.             rz_initreceiver := zcompl;
  1789.             exit
  1790.           end;
  1791.           z_sendhexheader(znak,txhdr);
  1792.           goto again
  1793.         end;
  1794.  
  1795.         zcompl,
  1796.         zfin: begin
  1797.           rz_initreceiver := zcompl;
  1798.           exit
  1799.         end;
  1800.  
  1801.         zcan,
  1802.         rcdo: begin
  1803.           rz_initreceiver := c;
  1804.           exit
  1805.         end
  1806.       end { case }
  1807.     end; { not zcarrier }
  1808.     z_message('Timeout');
  1809.     rz_initreceiver := zerror
  1810.   end;
  1811.  
  1812.  
  1813.  
  1814.   function rz_getheader: integer;
  1815.   var
  1816.     e, p, n, i: integer;
  1817.     multiplier: longint;
  1818.     s: string;
  1819.     ttime, tsize: longint;
  1820.     tname: string;
  1821.  
  1822.   begin
  1823.     isbinary := true;    { force the issue! }
  1824.     fsize := longint(0);
  1825.     p := 0;
  1826.     s := '';
  1827.     while (p < 255) and (secbuf[p] <> 0) do begin
  1828.       s := s + upcase(chr(secbuf[p]));
  1829.       inc(p)
  1830.     end;
  1831.     inc(p);
  1832.     (* get rid of drive & path specifiers *)
  1833.     while (pos(':',s) > 0) do delete(s,1,pos(':',s));
  1834.     while (pos('\',s) > 0) do delete(s,1,pos('\',s));
  1835.     fname := s;
  1836.     (**** done with name ****)
  1837.  
  1838.     fsize := longint(0);
  1839.     while (p < zbufsize) and (secbuf[p] <> $20) and (secbuf[p] <> 0) do begin
  1840.       fsize := (fsize *10) + ord(secbuf[p]) - $30;
  1841.       inc(p)
  1842.     end;
  1843.     inc(p);
  1844.     curfsize := fsize;
  1845.     (**** done with size ****)
  1846.  
  1847.  
  1848.     s := '';
  1849.     while (p < zbufsize) and (secbuf[p] in [$30..$37]) do begin
  1850.       s := s + chr(secbuf[p]);
  1851.       inc(p)
  1852.     end;
  1853.     inc(p);
  1854.     ftime := z_fromunixdate(s);
  1855.     (**** done with time ****)
  1856.  
  1857.     if (z_findfile(zrxpath+fname, tname, tsize, ttime)) then begin
  1858.       if (zconv = zcresum) and (fsize > tsize) then begin
  1859.         filestart := tsize;
  1860.         if (not z_openfile(outfile,zrxpath + fname)) then begin
  1861.           z_message('Error opening '+fname);
  1862.           rz_getheader := zerror;
  1863.           exit
  1864.         end;
  1865.         if (not z_seekfile(outfile,tsize)) then begin
  1866.           z_message('Error positioning file');
  1867.           rz_getheader := zerror;
  1868.           exit
  1869.         end;
  1870.         z_message('Recovering...')
  1871.       end else begin
  1872.         z_showname(fname);
  1873.         z_message('File is already complete');
  1874.         if (zconv = zcresum) then __logapp('File is already complete.') else
  1875.           __logapp('No resume command was given.');
  1876.         rz_getheader := zskip;
  1877.         exit
  1878.       end
  1879.     end else begin
  1880.       filestart := 0;
  1881.       if (not z_makefile(outfile,zrxpath + fname)) then begin
  1882.         z_message('Unable to create '+fname);
  1883.         rz_getheader := zerror;
  1884.         exit
  1885.       end
  1886.     end;
  1887.     z_showname(fname);
  1888.     z_showsize(fsize);
  1889.     z_showtransfertime(fsize,zbaud);
  1890.     if zmodemlogging then __logapp('Receiving: ' +
  1891.       fname + ' ' + __pntstr(curfsize) + ' ' + getxfrtime(fsize, zbaud)
  1892.     );
  1893.     rz_getheader := zok
  1894.   end;
  1895.  
  1896.  
  1897.  
  1898.   function rz_savetodisk(var rxbytes: longint): integer;
  1899.   begin
  1900.     if (keypressed) then if (readkey = #27) then begin
  1901.       z_message('Aborted from keyboard');
  1902.       if zmodemlogging then __logapp('Aborted from keyboard...');
  1903.       z_sendcan;
  1904.       rz_savetodisk := zerror;
  1905.       exit
  1906.     end;
  1907.     if (not z_writefile(outfile,secbuf,rxcount)) then begin
  1908.       z_message('Disk write error');
  1909.       if zmodemlogging then __logapp('Disk write error.');
  1910.       rz_savetodisk := zerror
  1911.     end else rz_savetodisk := zok;
  1912.     inc(rxbytes, rxcount);
  1913.     inc(totalbytes, rxcount);
  1914.   end;
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.   function rz_receivefile: integer;
  1921.   label
  1922.     err, nxthdr, moredata;
  1923.  
  1924.   var
  1925.     c, n: integer;
  1926.     rxbytes: longint;
  1927.     sptr: string;
  1928.     done: boolean;
  1929.  
  1930.   begin
  1931.     zerrors := 0; done := false; eofseen := false; oldl := 0;
  1932.     c := rz_getheader;
  1933.     if (c <> zok) then begin
  1934.       if (c = zskip) then tryzhdrtype := zskip;
  1935.       rz_receivefile := c; exit
  1936.     end;
  1937.     c := zok; n := 10; rxbytes := filestart; rxpos := filestart;
  1938.     ztime := z_settimer; zcps := 0; inc(filenum);
  1939.     repeat
  1940.       z_putlongintoheader(rxbytes);
  1941.       z_sendhexheader(zrpos,txhdr);
  1942. nxthdr:
  1943.       c := z_getheader(rxhdr);
  1944.       z_frame(c);
  1945.       case c of
  1946.         zdata: begin
  1947.           if (rxpos <> rxbytes) then begin
  1948.             dec(n);
  1949.             inc(zerrors);
  1950.             z_errors(zerrors);
  1951.             if (n < 0) then goto err;
  1952.             z_message('Bad position');
  1953.             z_putstring(attn)
  1954.           end else begin
  1955. moredata:
  1956.             c := rz_receivedata(secbuf,zbufsize);
  1957.             z_frame(c);
  1958.             case c of
  1959.               zcan,
  1960.               rcdo: goto err;
  1961.  
  1962.               zerror: begin
  1963.                 dec(n); inc(zerrors); z_errors(zerrors);
  1964.                 if (n < 0) then goto err;
  1965.                 z_putstring(attn)
  1966.               end;
  1967.  
  1968.               ztimeout: begin
  1969.                 dec(n); if (n < 0) then goto err
  1970.               end;
  1971.  
  1972.               gotcrcw: begin
  1973.                 n := 10;
  1974.                 c := rz_savetodisk(rxbytes);
  1975.                 if (c <> zok) then begin
  1976.                   rz_receivefile := c;
  1977.                   exit
  1978.                 end;
  1979.                 z_showloc(rxbytes);
  1980.                 z_putlongintoheader(rxbytes);
  1981.                 z_sendhexheader(zack,txhdr);
  1982.                 goto nxthdr
  1983.               end;
  1984.  
  1985.               gotcrcq: begin
  1986.                  n := 10;
  1987.                  c := rz_savetodisk(rxbytes);
  1988.                  if (c <> zok) then begin
  1989.                    rz_receivefile := c;
  1990.                    exit
  1991.                  end;
  1992.                  z_showloc(rxbytes);
  1993.                  z_putlongintoheader(rxbytes);
  1994.                  z_sendhexheader(zack,txhdr);
  1995.                  goto moredata
  1996.               end;
  1997.  
  1998.               gotcrcg: begin
  1999.                 n := 10;
  2000.                 c := rz_savetodisk(rxbytes);
  2001.                 if (c <> zok) then begin
  2002.                   rz_receivefile := c;
  2003.                   exit
  2004.                 end;
  2005.                 z_showloc(rxbytes);
  2006.                 goto moredata
  2007.               end;
  2008.  
  2009.               gotcrce: begin
  2010.                 n := 10;
  2011.                 c := rz_savetodisk(rxbytes);
  2012.                 if (c <> zok) then begin
  2013.                   rz_receivefile := c;
  2014.                   exit
  2015.                 end;
  2016.                 z_showloc(rxbytes);
  2017.                 goto nxthdr
  2018.               end
  2019.  
  2020.             end {case}
  2021.           end
  2022.         end; {case of zdata}
  2023.  
  2024.         znak,
  2025.         ztimeout: begin
  2026.           dec(n);
  2027.           if (n < 0) then goto err;
  2028.           z_showloc(rxbytes)
  2029.         end;
  2030.  
  2031.         zfile: begin
  2032.           c := rz_receivedata(secbuf,zbufsize);
  2033.           z_frame(c)
  2034.         end;
  2035.  
  2036.         zeof: if (rxpos = rxbytes) then begin
  2037.           rz_receivefile := c;
  2038.           exit
  2039.         end
  2040.  
  2041.         else goto nxthdr;
  2042.  
  2043.         zerror: begin
  2044.           dec(n);
  2045.           if (n < 0) then goto err;
  2046.           z_showloc(rxbytes);
  2047.           z_putstring(attn)
  2048.         end else begin
  2049.           c := zerror;
  2050.           goto err
  2051.         end
  2052.       end {case}
  2053.     until (not done);
  2054. err:
  2055.     rz_receivefile := zerror
  2056.   end; { rec file }
  2057.  
  2058.  
  2059.  
  2060.  
  2061.  
  2062.   function rz_receivebatch: integer;
  2063.   var
  2064.     s: string;
  2065.     c: integer;
  2066.     done: boolean;
  2067.  
  2068.   begin
  2069.     z_message('Receiving...');
  2070.     done := false; filenum := 1;
  2071.     while (not done) do begin
  2072.       if not (z_carrier) then begin
  2073.         rz_receivebatch := zerror;
  2074.         exit
  2075.       end;
  2076.       __write(x1 + 2, y2 - 1, bfore, bback, __rep(x4-x1-3,'░'));
  2077.       z_message('Receiving file #' + itos(filenum, 3));
  2078.       if zmodemlogging then __logapp('Receiving file #' + itos(filenum, 3));
  2079.       __attrib(x3+1, y1+1, x4-1, y2-2, bback, bback);
  2080.       c := rz_receivefile;
  2081.       if (z_settimer - ztime) <> 0 then 
  2082.         zcps := fsize div (z_settimer - ztime);
  2083.       z_frame(c);
  2084.       z_setftime(outfile,ftime);
  2085.       z_closefile(outfile);
  2086.       str(zcps:4, s);
  2087.       z_message(s+' cps');
  2088.       if zmodemlogging then __logapp(s + ' cps.');
  2089.       __write(x3, y1 + 13, bfore, bback, s +' cps');
  2090.       if zbaud > 0 then __write(x3, y1 + 14, bfore, bback, 
  2091.         itos(trunc(((zcps * 10) / zbaud) * 100), 3)
  2092.       );
  2093.       case c of
  2094.         zeof,
  2095.         zskip: begin
  2096.           c := rz_initreceiver;
  2097.           z_frame(c);
  2098.           case c of
  2099.             zfile: {null};
  2100.             zcompl: begin
  2101.               rz_ackbibi;
  2102.               rz_receivebatch := zok;
  2103.               exit
  2104.             end;
  2105.  
  2106.             else begin
  2107.               rz_receivebatch := zerror;
  2108.               exit
  2109.             end
  2110.           end
  2111.         end else begin
  2112.           rz_receivebatch := c;
  2113.           exit
  2114.         end
  2115.       end {case}
  2116.     end {while}
  2117.   end;
  2118.  
  2119.  
  2120.  
  2121.  
  2122.  
  2123.   function zmodem_receive(path: string; comport: word; baudrate: longint;
  2124.     init: boolean
  2125.   ): boolean;
  2126.   var i: integer;
  2127.   begin
  2128.     zbaud := baudrate; zport := comport; totalbytes := 0;
  2129.     z_openwindow(tpzver, 'Receiving');
  2130.     z_message('Initializing...');
  2131.     if init then if (not z_asyncon(comport,baudrate)) then begin
  2132.       z_message('Unable to open:');
  2133.       z_message(
  2134.         'Port: COM' + itos(comport, 1) + ' Baud: ' + itos(baudrate, 5)
  2135.       );
  2136.       delay(2000); zmodem_receive := false; exit
  2137.     end;
  2138.     zrxpath := path;
  2139.     if (zrxpath[length(zrxpath)] <> '\') and (zrxpath <> '') then
  2140.       zrxpath := zrxpath + '\';
  2141.     rxtimeout := 100;
  2142.     tryzhdrtype := zrinit;
  2143.     i := rz_initreceiver;
  2144.     if (i = zcompl) or ((i = zfile) and ((rz_receivebatch) = zok)) then begin
  2145.       z_message('Restoring async params');
  2146.       if init then z_asyncoff;
  2147.       zmodem_receive := true
  2148.     end else begin
  2149.       z_clearoutbound;
  2150.       z_message('Sending CAN');
  2151.       z_sendcan;
  2152.       z_message('Restoring async params');
  2153.       if init then z_asyncoff;
  2154.       zmodem_receive := false;
  2155.     end
  2156.   end;
  2157.  
  2158.  
  2159.  
  2160.  
  2161. (***************************************************)
  2162. (* send file routines                              *)
  2163. (***************************************************)
  2164.  
  2165.  
  2166. var
  2167.   infile   :    file;
  2168.   strtpos  : longint;
  2169.   rxbuflen : integer;
  2170.   txbuf    : buftype;
  2171.   blkred   : integer;
  2172.  
  2173.  
  2174.  
  2175.   procedure sz_z_sendbyte(b: byte);
  2176.   begin
  2177.     if (
  2178.       ((b and $7f) in [16,17,19,24]) or
  2179.       (((b and $7f) = 13) and ((lastsent and $7f) = 64))
  2180.     ) then begin
  2181.       z_sendbyte(zdle);
  2182.       lastsent := (b xor 64)
  2183.     end else lastsent := b;
  2184.     z_sendbyte(lastsent)
  2185.   end;
  2186.  
  2187.  
  2188.  
  2189.   procedure sz_sendbinaryhead32(htype: byte; var hdr: hdrtype);
  2190.   var
  2191.     crc: longint;
  2192.     n: integer;
  2193.  
  2194.   begin
  2195.     z_sendbyte(zpad); z_sendbyte(zdle); z_sendbyte(zbin32);
  2196.     sz_z_sendbyte(htype); crc := updc32(htype,$ffffffff);
  2197.     for n := 0 to 3 do begin
  2198.       sz_z_sendbyte(hdr[n]);
  2199.       crc := updc32(hdr[n],crc)
  2200.     end;
  2201.     crc := (not crc);
  2202.     for n := 0 to 3 do begin
  2203.       sz_z_sendbyte(byte(crc));
  2204.       crc := (crc shr 8)
  2205.     end;
  2206.     if (htype <> zdata) then delay(500)
  2207.   end;
  2208.  
  2209.  
  2210.  
  2211.  
  2212.   procedure sz_sendbinaryheader(htype: byte; var hdr: hdrtype);
  2213.   var
  2214.     crc: word;
  2215.     n: integer;
  2216.  
  2217.   begin
  2218.     if (usecrc32) then begin
  2219.       sz_sendbinaryhead32(htype,hdr);
  2220.       exit
  2221.     end;
  2222.     z_sendbyte(zpad); z_sendbyte(zdle); z_sendbyte(zbin);
  2223.     sz_z_sendbyte(htype); crc := updcrc(htype,0);
  2224.     for n := 0 to 3 do begin
  2225.       sz_z_sendbyte(hdr[n]);
  2226.       crc := updcrc(hdr[n],crc)
  2227.     end;
  2228.     crc := updcrc(0,crc); crc := updcrc(0,crc);
  2229.     sz_z_sendbyte(lo(crc shr 8));
  2230.     sz_z_sendbyte(lo(crc));
  2231.     if (htype <> zdata) then delay(500)
  2232.   end;
  2233.  
  2234.  
  2235.  
  2236.   procedure sz_sendda32(var buf: buftype; blength: integer; frameend: byte);
  2237.   var
  2238.     crc: longint;
  2239.     t: integer;
  2240.  
  2241.   begin
  2242.     crc := $ffffffff;
  2243.     for t := 0 to (blength - 1) do begin
  2244.       sz_z_sendbyte(buf[t]);
  2245.       crc := updc32(buf[t],crc)
  2246.     end;
  2247.     crc := updc32(frameend,crc); crc := (not crc);
  2248.     z_sendbyte(zdle); z_sendbyte(frameend);
  2249.     for t := 0 to 3 do begin
  2250.       sz_z_sendbyte(byte(crc));
  2251.       crc := (crc shr 8)
  2252.     end;
  2253.     begin
  2254.       z_sendbyte(17);
  2255.       delay(500)
  2256.     end
  2257.   end;
  2258.  
  2259.  
  2260.  
  2261.   procedure sz_senddata(var buf: buftype; blength: integer; frameend: byte);
  2262.   var
  2263.     crc: word;
  2264.     t: integer;
  2265.  
  2266.   begin
  2267.     if (usecrc32) then begin
  2268.       sz_sendda32(buf,blength,frameend);
  2269.       exit
  2270.     end;
  2271.     crc := 0;
  2272.     for t := 0 to (blength - 1) do begin
  2273.       sz_z_sendbyte(buf[t]);
  2274.       crc := updcrc(buf[t],crc)
  2275.     end;
  2276.     crc := updcrc(frameend,crc);
  2277.     z_sendbyte(zdle); z_sendbyte(frameend);
  2278.     crc := updcrc(0,crc); crc := updcrc(0,crc);
  2279.     sz_z_sendbyte(lo(crc shr 8)); sz_z_sendbyte(lo(crc));
  2280.     if (frameend = zcrcw) then begin
  2281.       z_sendbyte(17);
  2282.       delay(500)
  2283.     end
  2284.   end;
  2285.  
  2286.  
  2287.  
  2288.   procedure sz_endsend;
  2289.   var done: boolean;
  2290.   begin
  2291.     done := false;
  2292.     repeat
  2293.       z_putlongintoheader(txpos);
  2294.       sz_sendbinaryheader(zfin,txhdr);
  2295.       case z_getheader(rxhdr) of
  2296.         zfin: begin
  2297.           z_sendbyte(ord('O'));
  2298.           z_sendbyte(ord('O'));
  2299.           delay(500);
  2300.           z_clearoutbound;
  2301.           exit
  2302.         end;
  2303.         zcan,
  2304.         rcdo,
  2305.         zferr,
  2306.         ztimeout: exit
  2307.       end {case}
  2308.     until (done)
  2309.   end;
  2310.  
  2311.  
  2312.  
  2313.   function sz_getreceiverinfo: integer;
  2314.   var rxflags, n, c: integer;
  2315.   begin
  2316.     z_message('Getting info.');
  2317.     for n := 1 to 10 do begin
  2318.       c := z_getheader(rxhdr);
  2319.       z_frame(c);
  2320.       case c of
  2321.         zchallenge: begin
  2322.           z_putlongintoheader(rxpos);
  2323.           z_sendhexheader(zack,txhdr)
  2324.         end;
  2325.  
  2326.         zcommand: begin
  2327.           z_putlongintoheader(longint(0));
  2328.           z_sendhexheader(zrqinit,txhdr)
  2329.         end;
  2330.  
  2331.         zrinit: begin
  2332.           rxbuflen := (word(rxhdr[zp1]) shl 8) or rxhdr[zp0];
  2333.           usecrc32 := ((rxhdr[zf0] and canfc32) <> 0);
  2334.           z_showcheck(usecrc32);
  2335.           sz_getreceiverinfo := zok;
  2336.           exit
  2337.         end;
  2338.  
  2339.         zcan,
  2340.         rcdo,
  2341.         ztimeout: begin
  2342.           sz_getreceiverinfo := zerror;
  2343.           exit
  2344.         end else if (c <> zrqinit) or (rxhdr[zf0] <> zcommand) then
  2345.           z_sendhexheader(znak,txhdr)
  2346.       end {case}
  2347.     end; {for}
  2348.     sz_getreceiverinfo := zerror
  2349.   end;
  2350.  
  2351.  
  2352.  
  2353.   function sz_syncwithreceiver: integer;
  2354.   var
  2355.     c, num_errs: integer;
  2356.     done: boolean;
  2357.  
  2358.   begin
  2359.     num_errs := 7;
  2360.     done := false;
  2361.     repeat
  2362.       c := z_getheader(rxhdr);
  2363.       z_frame(c);
  2364.       z_clearinbound;
  2365.       case c of
  2366.         ztimeout: begin
  2367.           dec(num_errs);
  2368.           if (num_errs < 0) then begin
  2369.             sz_syncwithreceiver := zerror;
  2370.             exit
  2371.           end
  2372.         end;
  2373.  
  2374.         zcan,
  2375.         zabort,
  2376.         zfin,
  2377.         rcdo: begin
  2378.           sz_syncwithreceiver := zerror;
  2379.           exit
  2380.         end;
  2381.  
  2382.         zrpos: begin
  2383.           if (not z_seekfile(infile,rxpos)) then begin
  2384.             z_message('File seek error');
  2385.             sz_syncwithreceiver := zerror;
  2386.             exit
  2387.           end;
  2388.           z_message('Repositioning...');
  2389.           z_showloc(rxpos);
  2390.           txpos := rxpos;
  2391.           sz_syncwithreceiver := c;
  2392.           exit
  2393.         end;
  2394.  
  2395.         zskip,
  2396.         zrinit,
  2397.         zack: begin
  2398.           sz_syncwithreceiver := c;
  2399.           exit
  2400.         end else begin
  2401.           z_message('I dunno what happened!');
  2402.           sz_sendbinaryheader(znak,txhdr)
  2403.         end
  2404.       end {case}
  2405.     until done
  2406.   end;
  2407.  
  2408.  
  2409.  
  2410.  
  2411.   function sz_sendfiledata: integer;
  2412.   label waitack, somemore, oops;
  2413.   var
  2414.     c, e                     : integer;
  2415.     newcnt, blklen, blkred,
  2416.     maxblklen, goodblks,
  2417.     goodneeded               :    word;
  2418.  
  2419.   begin
  2420.     __write(x1 + 2, y2 - 1, bfore, bback, __rep(x4-x1-3,'░')); inc(filenum);
  2421.     z_message('Sending file #' + itos(filenum, 3)); oldl := 0;
  2422.     if zmodemlogging then __logapp('Sending file #' + itos(filenum, 3));
  2423.     goodneeded := 1;
  2424.     if (zbaud < 300) then maxblklen := 128 else
  2425.       maxblklen := (word(zbaud) div 300) * 256;
  2426.     if (maxblklen > zbufsize) then maxblklen := zbufsize;
  2427.     if (rxbuflen > 0) and (rxbuflen < maxblklen) then maxblklen := rxbuflen;
  2428.     blklen := maxblklen;
  2429.     ztime := z_settimer;
  2430. somemore:
  2431.     if (z_charavail) then begin
  2432. waitack:
  2433.       c := sz_syncwithreceiver;
  2434.       z_frame(c);
  2435.       case c of
  2436.         zskip: begin
  2437.           sz_sendfiledata := zskip;
  2438.           exit
  2439.         end;
  2440.  
  2441.         zack: {null};
  2442.         zrpos: begin
  2443.           inc(zerrors);
  2444.           z_errors(zerrors);
  2445.           if ((blklen shr 2) > 32) then blklen := (blklen shr 2) else
  2446.             blklen := 32;
  2447.           goodblks := 0;
  2448.           goodneeded := (goodneeded shl 1) or 1
  2449.         end;
  2450.  
  2451.         zrinit: begin
  2452.           sz_sendfiledata := zok;
  2453.           exit
  2454.         end else begin
  2455.           sz_sendfiledata := zerror;
  2456.           exit
  2457.         end
  2458.       end {case};
  2459.       while (z_charavail) do begin
  2460.         case (z_getbyte(1)) of
  2461.           can,
  2462.           zpad: goto waitack;
  2463.           rcdo: begin
  2464.             sz_sendfiledata := zerror;
  2465.             exit
  2466.           end
  2467.         end {case}
  2468.       end
  2469.     end; {if char avail}
  2470.     newcnt := rxbuflen;
  2471.     z_putlongintoheader(txpos);
  2472.     z_message('Sending data header');
  2473.     sz_sendbinaryheader(zdata,txhdr);
  2474.     z_message('Sending file data...');
  2475.     repeat
  2476.       if (keypressed) then if (readkey = #27) then begin
  2477.         z_message('Aborted from keyboard.');
  2478.         if zmodemlogging then __logapp('Aborted from keyboard.');
  2479.         z_sendcan;
  2480.         goto oops
  2481.       end;
  2482.       if (not z_carrier) then goto oops;
  2483.       if (not z_readfile(infile,txbuf,blklen,blkred)) then begin
  2484.         z_message('Error reading disk!');
  2485.         if zmodemlogging then __logapp('Error reading disk!');
  2486.         z_sendcan;
  2487.         goto oops
  2488.       end;
  2489.       if (blkred < blklen) then e := zcrce
  2490.       else if (rxbuflen <> 0) and ((newcnt - blkred) <= 0) then begin
  2491.         newcnt := (newcnt - blkred);
  2492.         e := zcrcw
  2493.       end else e := zcrcg;
  2494.       sz_senddata(txbuf,blkred,e);
  2495.       inc(txpos, blkred);
  2496.       inc(totalbytes, blkred);
  2497.       z_showloc(txpos);
  2498.       inc(goodblks);
  2499.       if (blklen < maxblklen) and (goodblks > goodneeded) then begin
  2500.          if ((blklen shl 1) < maxblklen) then blklen := (blklen shl 1) else
  2501.            blklen := maxblklen;
  2502.          goodblks := 0
  2503.       end;
  2504.       if (e = zcrcw) then goto waitack;
  2505.       while (z_charavail) do begin
  2506.         case z_getbyte(1) of
  2507.           can,
  2508.           zpad: begin
  2509.             z_message('Trouble?');
  2510.             if zmodemlogging then __logapp('Trouble?');
  2511.             z_clearoutbound;
  2512.             sz_senddata(txbuf,0,zcrce);
  2513.             goto waitack
  2514.           end;
  2515.  
  2516.           rcdo: begin
  2517.             sz_sendfiledata := zerror;
  2518.             exit
  2519.           end
  2520.         end {case}
  2521.       end {while}
  2522.     until (e <> zcrcg);
  2523.     repeat
  2524.       z_putlongintoheader(txpos);
  2525.       z_message('Sending EOF');
  2526.       sz_sendbinaryheader(zeof,txhdr);
  2527.       c := sz_syncwithreceiver;
  2528.       case c of
  2529.         zack: {null};
  2530.         zrpos: goto somemore;
  2531.         zrinit: begin
  2532.           sz_sendfiledata := zok;
  2533.           exit
  2534.         end;
  2535.  
  2536.         zskip: begin
  2537.           sz_sendfiledata := c;
  2538.           exit
  2539.         end else begin
  2540. oops:  
  2541.           sz_sendfiledata := zerror;
  2542.           exit
  2543.         end
  2544.       end {case}
  2545.     until (c <> zack)
  2546.   end;
  2547.  
  2548.  
  2549.  
  2550.  
  2551.   function sz_sendfile: integer;
  2552.   var
  2553.     c: integer;
  2554.     done: boolean;
  2555.  
  2556.   begin
  2557.     zerrors := word(0);
  2558.     done := false;
  2559.     repeat
  2560.       if (keypressed) then if (readkey = #27) then begin
  2561.         z_sendcan;
  2562.         z_message('Aborted from keyboard');
  2563.         if zmodemlogging then __logapp('Aborted from keyboard');
  2564.         sz_sendfile := zerror;
  2565.         exit
  2566.       end;
  2567.       if (not z_carrier) then begin
  2568.         z_message('Lost carrier.');
  2569.         if zmodemlogging then __logapp('Lost carrier.');
  2570.         sz_sendfile := zerror;
  2571.         exit
  2572.       end;
  2573.       fillchar(txhdr,4,0);
  2574.       txhdr[zf0] := zcresum; {recover}
  2575.       sz_sendbinaryheader(zfile,txhdr);
  2576.       sz_senddata(txbuf,zbufsize,zcrcw);
  2577.       repeat
  2578.         c := z_getheader(rxhdr);
  2579.         z_frame(c);
  2580.         case c of
  2581.           zcan,
  2582.           rcdo,
  2583.           ztimeout,
  2584.           zfin,
  2585.           zabort: begin
  2586.             sz_sendfile := zerror;
  2587.             exit
  2588.           end;
  2589.  
  2590.           zrinit: {null - this will cause a loopback};
  2591.  
  2592.           zcrc: begin
  2593.             z_putlongintoheader(z_filecrc32(infile));
  2594.             z_sendhexheader(zcrc,txhdr)
  2595.           end;
  2596.  
  2597.           zskip: begin
  2598.             sz_sendfile := c;
  2599.             exit
  2600.           end;
  2601.  
  2602.           zrpos: begin
  2603.             if (not z_seekfile(infile,rxpos)) then begin
  2604.                z_message('File positioning error.');
  2605.                if zmodemlogging then __logapp('File positioning error.');
  2606.                z_sendhexheader(zferr,txhdr);
  2607.                sz_sendfile := zerror;
  2608.                exit
  2609.             end;
  2610.             z_message('Setting start position');
  2611.             z_showloc(rxpos);
  2612.             strtpos := rxpos;
  2613.             txpos := rxpos;
  2614.             sz_sendfile := sz_sendfiledata;
  2615.             exit
  2616.           end
  2617.         end {case}
  2618.       until (c <> zrinit)
  2619.     until done
  2620.   end;
  2621.  
  2622.  
  2623.  
  2624.  
  2625.  
  2626.  
  2627.   function zmodem_send(
  2628.     pathname: string; lastfile: boolean; comport: word; baudrate: longint;
  2629.     init: boolean
  2630.   ): boolean;
  2631.   var
  2632.     s: string;
  2633.     n: integer;
  2634.   
  2635.   begin
  2636.     zerrors := 0; totalbytes := 0; zbaud := baudrate; zport := comport;
  2637.     z_openwindow(tpzver, 'Sending');
  2638.     if init then if (not z_asyncon(comport,baudrate)) then begin
  2639.       z_message('Unable to open port'); delay(2000);
  2640.       zmodem_send := false; exit
  2641.     end;
  2642.     if (not z_carrier) then begin
  2643.       z_message('Lost carrier'); delay(2000); if init then z_asyncoff;
  2644.       zmodem_send := false;
  2645.       exit
  2646.     end;
  2647.     if (not z_findfile(pathname, fname, fsize, ftime)) then begin
  2648.       z_message('Unable to find/open file'); sz_endsend;
  2649.       if lastfile then if init then z_asyncoff; zmodem_send := false; exit
  2650.     end;
  2651.     z_message(__packfil(pathname, x2-x4-2));
  2652.     z_showname(fname); z_showsize(fsize); z_showtransfertime(fsize, zbaud);
  2653.     str(fsize,s); s := (fname + #0 + s + ' '); s := s + z_tounixdate(ftime);
  2654.     n := length(s);
  2655.     for n := 1 to length(s) do begin
  2656.       if (s[n] in ['A'..'Z']) then s[n] := chr(ord(s[n]) + $20)
  2657.     end;
  2658.     fillchar(txbuf,zbufsize,0); move(s[1],txbuf[0],length(s));
  2659.     if (zbaud > 0) then rxtimeout := integer(614400 div zbaud) else
  2660.       rxtimeout := 100;
  2661.     if (rxtimeout < 100) then rxtimeout := 100;
  2662.     attn[0] := ord('r'); attn[1] := ord('z'); attn[3] := 13; attn[4] := 0;
  2663.     z_putstring(attn);
  2664.     fillchar(attn,sizeof(attn),0); z_putlongintoheader(longint(0));
  2665.     z_message('Sending ZRQINIT');
  2666.     z_sendhexheader(zrqinit,txhdr);
  2667.     if (sz_getreceiverinfo = zerror) then begin
  2668.       if init then z_asyncoff; zmodem_send := false; exit
  2669.     end;
  2670.     if (not z_openfile(infile,pathname)) then
  2671.     if (ioresult <> 0) then begin
  2672.       z_message('Failure to open file'); z_sendcan; if init then z_asyncoff;
  2673.       zmodem_send := false; exit
  2674.     end;
  2675.     n := sz_sendfile;
  2676.     if (z_settimer - ztime) <> 0 then 
  2677.       zcps := (fsize div (z_settimer - ztime));
  2678.     z_closefile(infile); z_frame(n);
  2679.     z_message(itos(zcps, 4) + ' cps');
  2680.     if zmodemlogging then __logapp(itos(zcps, 4) + ' cps');
  2681.     if lastfile then begin
  2682.       if n = zok then sz_endsend else ; {z_sendcan;}
  2683.       {no: receive after this will fault then as well}
  2684.       if init then z_asyncoff;
  2685.     end;
  2686.     zmodem_send := true
  2687.   end;
  2688.  
  2689.  
  2690. begin    
  2691.   totalbytes := 0; filenum := 0; oldl := 0;
  2692. end.
  2693.