home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / PCZ40690.ZIP / SUPERZ.DOC < prev   
Encoding:
Text File  |  1990-11-27  |  27.8 KB  |  1,157 lines

  1. 00 07:12:00 11/27/1990
  2.  
  3.  
  4.  
  5.  
  6. "Super_Z" definitions and specifications:
  7.  
  8.  
  9. Super_Z is a trademark name of Personalized Computer
  10. Programming Company "PC²" denoting a method of zmodem file
  11. transfer enhancement.
  12.  
  13. You may/should use the name to refer to this enhancement
  14. method in your own zmodem application without concern.  All
  15. we ask is that you inform everyone in your documentation
  16. that Super_Z was developed and the name coined by PC².
  17.  
  18. If you use Super_Z in a commercial environment, great!  We
  19. hope you have much success but we don't want your money.
  20.  
  21. It's payment enough just knowing you appreciate the work I
  22. put into it.
  23.  
  24.  
  25. "Super_Z" works it's magic by NOT working so hard.  Zmodem
  26. adapts itself to environments that require an XON/XOFF
  27. handshake by "escaping" them along with several packet
  28. switching and ASCII communication control characters.  Thus
  29. the nets work properly and zmodem transfers the binary data
  30. successfully.  Knowing this then, it is easy to see why
  31. Super_Z will not function over nets that use XON/XOFF
  32. protocol or require other special triggers etc...  Super_Z
  33. is implemented in such a way that it will only work over
  34. nets that do not eat comm ctrl characters.  Basically, if a
  35. Ymodem-g transfer will work Super_Z will work better.
  36.  
  37.  
  38. The first and hardest "method setup" is the implementation
  39. of variable header lengths as described by Chuck Forsberg.
  40. Throughout this document we will use terminology and
  41. constant naming set forth by him in the P.D. release of
  42. zmodem.  We will not attempt to highlight our own from his
  43. since that's not what we're about.
  44.  
  45.  
  46. When I say the "hardest", I do not mean difficult.  Below is
  47. some commented sections of Turbo Pascal code showing
  48. variables and the various constant values needed to
  49. implement variable headers, super_z etc...
  50.  
  51. {Global Constant Values Common To Send & Rcvr}
  52.  
  53.   CANVHDR    = 01; {can use variable header flag}
  54.  
  55.   FrameTypes = 20; {number of zmodem header types allowed att}
  56.  
  57.   CANSUPERZ  = 04; {wants to use super_z transfer}
  58.  
  59.   GOFORSUPZ  = 01; {rcvr says we can transfer Super_Z}
  60.  
  61.  
  62.  
  63.  
  64. {Global "Static for 'C' folks" Turbo Pascal Typed Constants}
  65.  
  66.   RXHDRLEN : integer = 4; {specifies the header length common to both
  67.                            send and receive routines}
  68.  
  69.   USEVHDR  : boolean = false; {true/false value determines the use of
  70.                                variable length headers for both send
  71.                                and receive routines}
  72.  
  73.   VHDRTYPE : byte    = 0; {contains on of the six zmodem header
  74.                            values}
  75.  
  76.   WANTSUPERZ : boolean = false; {sets to TRUE if rcvr requests a }
  77.                                 {Super_Z transfer                }
  78.  
  79.   TRYSUPERZ : boolean = false; {sets to true if user wants to try}
  80.                                {for Super_Z transfer             }
  81.  
  82.  
  83.  
  84.  
  85. {Turbo Pascal Data Types}
  86. TYPE
  87.   hdrtype = ARRAY[ 0..15 ] OF byte; {16 byte maximum header length}
  88.  
  89.  
  90.  
  91.  
  92.  
  93.   {you may elect to add this procedure or simply put it in your}
  94.   {sendzbyte routine.  Either way will work fine.  Below are my}
  95.   {byte send routines as used in PCZ}
  96.  
  97.   PROCEDURE S_SendByte(b : byte);
  98.   BEGIN
  99.     IF (lo(b) = zdle) THEN  {escape only the zdle sequence}
  100.       BEGIN
  101.         SendByte(zdle);
  102.         lastsent := (zdle XOR $40); {send "zdle" as "zdlee"}
  103.       END
  104.     ELSE
  105.       lastsent := lo(b);
  106.  
  107.     SendByte(lastsent);
  108.   END;
  109.  
  110.  
  111.   PROCEDURE SendZByte(b : byte);
  112.   BEGIN
  113.     IF Super_Z Then  {if super_z is active then jumb to}
  114.       Begin            {the "S"uper SendByte routine   }
  115.         S_SendByte(b);
  116.         Exit;
  117.       End;
  118.  
  119.     IF ((b AND $60) <> 0) THEN
  120.       BEGIN
  121.         lastsent := b;
  122.       END
  123.     ELSE
  124.       BEGIN
  125.         CASE (b AND $7F) OF  {determine a set of known comm ctrl}
  126.           24,                {characters.  You could just as easily}
  127.           16,                {include all of them but be prepared for}
  128.           17,                {a decrease in performance}
  129.           19 : BEGIN
  130.                  SendByte(zdle);
  131.                  lastsent := (b XOR $40);
  132.                END;
  133.  
  134.           13 : IF (NOT zctlesc) AND ((lastsent AND $7F) <> $40) THEN
  135.                  lastsent := b
  136.                ELSE
  137.                  BEGIN
  138.                    SendByte(zdle);
  139.                    lastsent := (b XOR $40);
  140.                  END;
  141.  
  142.         ELSE
  143.           BEGIN
  144.             IF (zctlesc) AND ((b AND $60) <= 0) THEN
  145.               BEGIN
  146.                 SendByte(zdle);
  147.                 lastsent := (b XOR $40);
  148.               END
  149.             ELSE
  150.               lastsent := b;
  151.           END;
  152.         END;
  153.  
  154.       END;
  155.  
  156.     SendByte(lastsent);
  157.   END;
  158.  
  159.  
  160.  
  161.  
  162. {The next three procedures demonstrate the sending of variable length}
  163. {headers.  Your naming convention may be different but that should   }
  164. {be no problem if you're adding this to your implementation          }
  165.  
  166.  
  167.  
  168.   PROCEDURE SendHexHeader(len,             {Hdr length "4 - 15" bytes}
  169.                           htype : byte;    {zmodem frame indicator   }
  170.                                            {"zrqinit etc...          }
  171.                       VAR hdr   : hdrtype);{actual header buffer     }
  172.  
  173.   VAR
  174.     crc     : word;
  175.     n, i    : integer;
  176.   BEGIN
  177.     SendByte(zpad);
  178.     SendByte(zpad);
  179.     SendByte(zdle);
  180.  
  181.     If USEVHDR Then      {If we're using variable header lengths then}
  182.       Begin              {send HDRTYPE 'zvhex' byte and length 'len' }
  183.         SendByte(zvhex);
  184.         SendHexByte(len);
  185.       End
  186.     Else                 {otherwise send standard 'zhex' HDRTYPE}
  187.       SendByte(zhex);
  188.  
  189.     SendHexByte(htype);
  190.  
  191.     crc := updcrc(htype, 0);
  192.  
  193.     FOR n := 0 TO (len-1) DO {'len' is header length. My buffer is}
  194.       BEGIN                  {0-15 so len-1 corrects offset       }
  195.         SendHexByte(hdr[n]);
  196.         crc := updcrc(hdr[n], crc)
  197.       END;
  198.  
  199.     crc := updcrc(0, crc);
  200.     crc := updcrc(0, crc);
  201.  
  202.  
  203.   etc...
  204.  
  205.   END;
  206.  
  207.  
  208.  
  209.   PROCEDURE SendBinaryHeader32(len,             {ditto above}
  210.                                htype : byte;    {  "     "  }
  211.                            VAR hdr : hdrtype);  {  "     "  }
  212.   VAR
  213.     crc     : longint;
  214.     n       : integer;
  215.   BEGIN
  216.  
  217.     IF USEVHDR THEN         {this method is the same as for the }
  218.       BEGIN                 {hex header procedure               }
  219.         SendByte(zvbin32);
  220.         SendZByte(len);
  221.       END
  222.     ELSE
  223.       SendByte(zbin32);
  224.  
  225.     SendZByte(htype);
  226.  
  227.     crc := updc32(htype, $ffffffff);
  228.     FOR n := 0 TO (len-1) DO
  229.       BEGIN
  230.         SendZByte(hdr[n]);
  231.         crc := updc32(hdr[n], crc)
  232.       END;
  233.  
  234.  
  235.   etc...
  236.  
  237.   END;
  238.  
  239.  
  240.  
  241.   PROCEDURE SendBinaryHeader(len,              {ditto}
  242.                              htype : byte;     {  "  }
  243.                          VAR hdr : hdrtype);   {  "  }
  244.   VAR
  245.     crc     : word;
  246.     n       : integer;
  247.   BEGIN
  248.     SendByte(zpad);
  249.     SendByte(zdle);
  250.  
  251.     IF (usecrc32) THEN
  252.       BEGIN
  253.         SendBinaryHeader32(len, htype, hdr);
  254.         exit;
  255.       END;
  256.  
  257.     IF USEVHDR THEN        { same as above }
  258.       BEGIN
  259.         SendByte(zvbin);
  260.         SendZByte(len);
  261.       END
  262.     ELSE
  263.       SendByte(zbin);
  264.  
  265.     SendZByte(htype);
  266.  
  267.     crc := updcrc(htype, 0);
  268.  
  269.     FOR n := 0 TO (len-1) DO
  270.       BEGIN
  271.         SendZByte(hdr[n]);
  272.         crc := updcrc(hdr[n], crc)
  273.       END;
  274.  
  275.   etc...
  276.  
  277.   END;
  278.  
  279.  
  280.  
  281.  
  282.  
  283.   {these routines retrieve and place values in the first 4 positions}
  284.   {of the header.  The entire header is zero'd out in the case of   }
  285.   {put long in.  Our other cell values are add after the call to    }
  286.   {this routine }
  287.  
  288.  
  289.   FUNCTION PullLongFromHeader(VAR thishdr : hdrtype) : longint;
  290.   VAR
  291.     l       : longint;
  292.   BEGIN
  293.     l := longint(0);
  294.     l := thishdr[zp3];
  295.     l := (l SHL 8) OR thishdr[zp2];
  296.     l := (l SHL 8) OR thishdr[zp1];
  297.     l := (l SHL 8) OR thishdr[zp0];
  298.     PullLongFromHeader := l;
  299.   END;
  300.  
  301.   PROCEDURE PutLongInHeader(l : longint);
  302.   BEGIN
  303.     txhdr[zp0] := byte(l);
  304.     txhdr[zp1] := byte(l SHR 8);
  305.     txhdr[zp2] := byte(l SHR 16);
  306.     txhdr[zp3] := byte(l SHR 24)
  307.     txhdr[4]   := byte(0);       {clear entire header}
  308.     txhdr[5]   := byte(0);
  309.     txhdr[6]   := byte(0);
  310.     txhdr[7]   := byte(0);
  311.     txhdr[8]   := byte(0);
  312.     txhdr[9]   := byte(0);
  313.     txhdr[10]  := byte(0);
  314.     txhdr[11]  := byte(0);
  315.     txhdr[12]  := byte(0);
  316.     txhdr[13]  := byte(0);
  317.     txhdr[14]  := byte(0);
  318.     txhdr[15]  := byte(0);
  319.   END;
  320.  
  321.  
  322.  
  323.   {there are a couple of changes to the zdl get routine that need}
  324.   {to be made in order to pass the comm ctrl characters}
  325.  
  326.   FUNCTION GetZdlSeq : integer;
  327.   LABEL
  328.     loop, loopa;
  329.   VAR
  330.     c       : integer;
  331.   BEGIN
  332.   loop:
  333.     c := GetZByte(defaultwaittime);
  334.  
  335.     IF ((c AND $60) > 0) THEN
  336.       BEGIN
  337.         GetZdlSeq := c;
  338.         exit;
  339.       END;
  340.  
  341.     IF (c = zdle) THEN
  342.       GOTO loopa
  343.  
  344.     ELSE
  345.  
  346.       IF ((NOT Super_Z) AND (c IN [19, 17])) OR   {not super_z}
  347.       ((zctlesc) AND (((c AND $60) = 0))) THEN
  348.         GOTO loop
  349.  
  350.       ELSE
  351.         BEGIN
  352.           GetZdlSeq := c;
  353.           exit;
  354.         END;
  355.  
  356. loopa:
  357.     c := GetZByte(defaultwaittime);
  358.  
  359.     IF (c = can) THEN
  360.       BEGIN
  361.         c := GetZByte(defaultwaittime);
  362.         IF (c = can) THEN
  363.           BEGIN
  364.             c := GetZByte(defaultwaittime);
  365.             IF (c = can) THEN
  366.               c := GetZByte(defaultwaittime);
  367.           END
  368.       END;
  369.  
  370.     CASE c OF
  371.       can : GetZdlSeq := gotcan;
  372.       zcrce,
  373.       zcrcg,
  374.       zcrcq,
  375.       zcrcw : GetZdlSeq := (c OR gotor);
  376.       zrub0 : GetZdlSeq := $7f;
  377.       zrub1 : GetZdlSeq := $ff;
  378.                                                {not super_z}
  379.       19, 17 : IF (NOT super_z) THEN GOTO loopa ELSE GetZdlSeq := c;
  380.  
  381.     ELSE
  382.       BEGIN
  383.  
  384.         IF ((zctlesc) AND (((c AND $60) = 0))) THEN
  385.           GOTO loopa;
  386.  
  387.  
  388.         IF ((c AND $60) = $40) THEN
  389.           GetZdlSeq := (c XOR $40)
  390.         ELSE
  391.           IF (c IN [1..31]) Then
  392.             GetZdlSeq := c
  393.           ELSE
  394.             GetZdlSeq := zerror;
  395.       END;
  396.     END;                     {case}
  397.  
  398.   END;
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.   {The next three routines are the receive portion of the variable}
  406.   {header scheme.  They amount to nothing more than getting a byte}
  407.   {for the header RXHDRLEN-1 times}
  408.  
  409.  
  410.   FUNCTION GetHexHeader(VAR hdr : hdrtype) : integer;
  411.   VAR
  412.     crc     : word;
  413.     c, n    : integer;
  414.   BEGIN
  415.     c := GetHexByte;
  416.     IF (c < 0) THEN
  417.       BEGIN
  418.         GetHexHeader := c;
  419.         exit
  420.       END;
  421.     rxtype := c;
  422.     crc := updcrc(rxtype, 0);
  423.  
  424.     {get the header}
  425.     FOR n := 0 TO (RXHDRLEN-1) DO  {global value  length of header-1}
  426.       BEGIN                        {allow for 0- offset}
  427.         c := GetHexByte;
  428.         IF (c < 0) THEN
  429.           BEGIN
  430.             GetHexHeader := c;
  431.             exit
  432.           END;
  433.         hdr[n] := lo(c);
  434.         crc := updcrc(lo(c), crc)
  435.       END;
  436.  
  437.  
  438.   etc...
  439.  
  440.   END;
  441.  
  442.  
  443.  
  444.   FUNCTION GetBinaryHeader(VAR hdr : hdrtype) : integer;
  445.   VAR
  446.     crc     : word;
  447.     c, n    : integer;
  448.   BEGIN
  449.     c := GetZdlSeq;
  450.     IF (c < 0) THEN
  451.       BEGIN
  452.         GetBinaryHeader := c;
  453.         exit
  454.       END;
  455.     rxtype := c;
  456.     crc := updcrc(rxtype, 0);
  457.  
  458.     {get the header}
  459.     FOR n := 0 TO (RXHDRLEN-1) DO  {ditto}
  460.       BEGIN
  461.         c := GetZdlSeq;
  462.         IF (hi(c) <> 0) THEN
  463.           BEGIN
  464.             GetBinaryHeader := c;
  465.             exit
  466.           END;
  467.         hdr[n] := lo(c);
  468.         crc := updcrc(lo(c), crc)
  469.       END;
  470.  
  471.  
  472.   etc...
  473.  
  474.   END;
  475.  
  476.  
  477.  
  478.  
  479.   FUNCTION GetBinaryHeader32(VAR hdr : hdrtype) : integer;
  480.   VAR
  481.     crc     : longint;
  482.     c, n    : integer;
  483.   BEGIN
  484.     c := GetZdlSeq;
  485.     IF (c < 0) THEN
  486.       BEGIN
  487.         GetBinaryHeader32 := c;
  488.         exit
  489.       END;
  490.     rxtype := c;
  491.  
  492.     crc := updc32(rxtype, $ffffffff);
  493.  
  494.     {get the header}
  495.     FOR n := 0 TO (RXHDRLEN-1) DO  {ditto}
  496.       BEGIN
  497.         c := GetZdlSeq;
  498.         IF (hi(c) <> 0) THEN
  499.           BEGIN
  500.             GetBinaryHeader32 := c;
  501.             exit;
  502.           END;
  503.         hdr[n] := lo(c);
  504.         crc := updc32(lo(c), crc)
  505.       END;
  506.  
  507.  
  508.   etc...
  509.  
  510.   END;
  511.  
  512.  
  513.  
  514.  
  515.  
  516.   FUNCTION GetHeader(VAR hdr : hdrtype) : integer;
  517.   LABEL
  518.     gotcan, again, agn2, splat, done;
  519.   VAR
  520.     c, n, cancount : integer;
  521.   BEGIN
  522.     n := zbaud * 2;
  523.     cancount := 5;
  524.   again:
  525.  
  526.     IF (escape) THEN
  527.       BEGIN
  528.         CanThisXfer;
  529.         Say('transfer cancelled from keyboard');
  530.         GetHeader := zcan;
  531.         exit;
  532.       END;
  533.  
  534.     frameindicator := 0;
  535.     rxtype := 0;
  536.  
  537.     c := GetNoCtrlByte;
  538.  
  539.     CASE c OF
  540.       zpad :;
  541.       fubar,
  542.       rcdo,
  543.       ztimeout : GOTO done;
  544.  
  545.       can : BEGIN
  546.             gotcan:
  547.               dec(cancount);
  548.               IF (cancount < 0) THEN
  549.                 BEGIN
  550.                   c := zcan;
  551.                   GOTO done
  552.                 END;
  553.               c := GetZByte(10);
  554.               CASE c OF
  555.                 ztimeout : GOTO again;
  556.                 zcrcw : BEGIN
  557.                           c := zerror;
  558.                           GOTO done
  559.                         END;
  560.                 fubar,
  561.                 rcdo : GOTO done;
  562.                 can : BEGIN
  563.                         dec(cancount);
  564.                         IF (cancount < 0) THEN
  565.                           BEGIN
  566.                             c := zcan;
  567.                             GOTO done
  568.                           END;
  569.                         GOTO again
  570.                       END
  571.               END;
  572.             END;
  573.     ELSE
  574.  
  575.   agn2:
  576.       BEGIN
  577.         dec(n);
  578.         IF (n < 0) THEN
  579.           BEGIN
  580.             inc(zerrors);
  581.             ShowErrors(zerrors);
  582.             Say('header got trashed');
  583.             GetHeader := zerror;
  584.             exit;
  585.           END;
  586.  
  587.         IF (c <> can) THEN
  588.           cancount := 5;
  589.  
  590.         GOTO again;
  591.       END;
  592.     END;
  593.  
  594.     cancount := 5;
  595.  
  596.   splat:
  597.     c := GetNoCtrlByte;
  598.  
  599.     CASE c OF
  600.       zdle :;
  601.       zpad : GOTO splat;
  602.       fubar,
  603.       rcdo,
  604.       ztimeout : GOTO done;
  605.       ELSE
  606.         GOTO agn2;
  607.     END;
  608.  
  609.     c := GetNoCtrlByte;
  610.  
  611.     RXHDRLEN := 4; {Set global hdrlen to std value of 4}
  612.  
  613.     CASE c OF
  614.       zbin32 : BEGIN
  615.                  frameindicator := zbin32;
  616.                  c := GetBinaryHeader32(hdr);
  617.                END;
  618.       zbin   : BEGIN
  619.                  frameindicator := zbin;
  620.                  c := GetBinaryHeader(hdr);
  621.                END;
  622.       zhex   : BEGIN
  623.                  frameindicator := zhex;
  624.                  c := GetHexHeader(hdr);
  625.                END;
  626.  
  627.       {These 3 types signal a variable length header is coming}
  628.       zvbin32: BEGIN
  629.                  RXHDRLEN := GetZByte(defaultwaittime); {get length}
  630.                  If (RXHDRLEN < 0) Then goto done; {ensure range is}
  631.                  If (RXHDRLEN > 16) Then goto agn2;{valid          }
  632.                  frameindicator := zvbin32;  {set global type frame}
  633.                  c := GetBinaryHeader32(hdr);{go get the header    }
  634.                END;
  635.       zvbin  : BEGIN
  636.                  RXHDRLEN := GetZByte(defaultwaittime); {ditto}
  637.                  If (RXHDRLEN < 0) Then goto done;
  638.                  If (RXHDRLEN > 16) Then goto agn2;
  639.                  frameindicator := zvbin;
  640.                  c := GetBinaryHeader(hdr);
  641.                END;
  642.       zvhex  : BEGIN
  643.                  RXHDRLEN := GetHexByte; {ditto}
  644.                  If (RXHDRLEN < 0) Then goto done;
  645.                  If (RXHDRLEN > 16) Then goto agn2;
  646.                  frameindicator := zvhex;
  647.                  c := GetHexHeader(hdr);
  648.                END;
  649.       can : GOTO gotcan;
  650.       fubar,
  651.       rcdo,
  652.       ztimeout : GOTO done
  653.     ELSE
  654.       GOTO agn2
  655.     END;
  656.  
  657.     rxpos := PullLongFromHeader(hdr);
  658.  
  659.   done:
  660.  
  661.     {this portion of code basically says that if the headertype is}
  662.     {a valid type and the FrameType is in the alpha lower case range}
  663.     {then we must have received a variable header so set the global}
  664.     {flag to reflect the status ... either/or}
  665.  
  666.     If (c >= 0) AND (c <= FrameTypes) AND ((frameindicator and 32)<>0) Then
  667.       USEVHDR := TRUE;
  668.  
  669.     GetHeader := c
  670.   END;
  671.  
  672.  
  673.  
  674.  
  675.  
  676. {------------------------------------------------------------------}
  677. (* until otherwise stated the following routines are transmitter  *)
  678. (* specific routines                                              *)
  679. {------------------------------------------------------------------}
  680.  
  681.  
  682.  
  683. {GetRcvrInfo is the first xmitting done to the rcvr from the xmiter}
  684. {We use this routine to first signal the rcvr that we can use}
  685. {variable headers.  This is done by placing the value CANVHDR in}
  686. {header position zf3 of the zrqinit header}
  687.  
  688. {This is where we will also see that the rcvr can use variable hdr}
  689. {lengths as well as the rcvr's call for a Super_Z transfer.       }
  690. {Examine the code and you will understand the method used here.}
  691.  
  692.  
  693.   FUNCTION GetRcvrInfo : integer;
  694.   VAR
  695.     n, c    : integer;
  696.   BEGIN
  697.  
  698.     Say('getting receiver status info.');
  699.     n := 0;
  700.  
  701.     FOR n := 1 TO 10 DO
  702.       BEGIN
  703.  
  704.  
  705.         txhdr[zf3] := CANVHDR; {signal we can xmit variable headers}
  706.  
  707.  
  708.         SendHexHeader(4, zrqinit, txhdr);  {std hdrlen of 4}
  709.  
  710.         fillchar(rxhdr, sizeof(rxhdr), #0);
  711.  
  712.         c := GetHeader(rxhdr);  {get the rcvr's header which should be}
  713.                                 {for our concern a zrinit header}
  714.         ShowHdrInfo(c);
  715.  
  716.         CASE c OF
  717.           zchallenge : BEGIN
  718.                          PutLongInHeader(rxpos);
  719.                          SendHexHeader(4, zack, txhdr)
  720.                        END;
  721.           zcommand : BEGIN
  722.                        PutLongInHeader(longint(0));
  723.                        SendHexHeader(4, zrqinit, txhdr)
  724.                      END;
  725.  
  726.           zrinit : BEGIN {all good info is here}
  727.  
  728.                      {get length of rcvr input buffer here}
  729.  
  730.                      rxbuflen := ((rxhdr[zp1]) SHL 8) OR rxhdr[zp0];
  731.  
  732.  
  733.                      {can the rcvr handle 32bit crc checks}
  734.  
  735.                      usecrc32 := ((rxhdr[zf0] AND canfc32)<>0);
  736.  
  737.  
  738.                      {can the rcvr handle variable header lengths}
  739.                      {if true the rcvr will have placed CANVHDR value}
  740.                      {in header cell "zf1"                           }
  741.  
  742.                      USEVHDR  := ((rxhdr[zf1] AND canvhdr)<>0);
  743.  
  744.  
  745.                      {is the rcvr requesting a Super_Z transfer?}
  746.                      {if true the rcvr will have OR'd CANSUPERZ value}
  747.                      {into header cell "zf1".  WantSuperZ will flag  }
  748.                      {us later to respond                            }
  749.  
  750.                      WantSuperZ := ((rxhdr[zf1] AND cansuperz)<>0);
  751.  
  752.  
  753.  
  754.                      GetRcvrInfo := zok;
  755.                      ShowTransferType(usecrc32);
  756.                      exit;
  757.  
  758.                    END;
  759.           zcan,
  760.           fubar,
  761.           rcdo : BEGIN
  762.                    GetRcvrInfo := zerror;
  763.                    exit
  764.                  END;
  765.           ztimeout : {just let it loop} ;
  766.         ELSE
  767.           IF ( (c<>zrinit) OR (rxhdr[zf0]<>zcommand) ) THEN
  768.             BEGIN
  769.               SendHexHeader(4, znak, txhdr)
  770.             END;
  771.         END;                 {case}
  772.  
  773.         IF (NOT carrier) OR (escape) THEN n := 10;
  774.  
  775.       END;                   {for}
  776.     GetRcvrInfo := zerror;
  777.   END;
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.   FUNCTION SendFile(VAR blen : integer) : integer;
  787.   VAR
  788.     c       : integer;
  789.     done    : boolean;
  790.   BEGIN
  791.     zerrors := word(0);
  792.     done := false;
  793.  
  794.     REPEAT
  795.  
  796.       fillchar(txhdr, sizeof(txhdr), 0);
  797.  
  798.       IF recover THEN
  799.         txhdr[zf0] := zcresum {resume crashed file  }
  800.       ELSE
  801.         txhdr[zf0] := zcbin;  {normal file xfer}
  802.  
  803.  
  804.       {signal we still want variable header lengths used}
  805.  
  806.       txhdr[zf3] := canvhdr;
  807.  
  808.  
  809.  
  810.       {This is where we really find out what we can do.  If the}
  811.       {user wants to TRYSUPERZ or the rcvr WANTSUPERZ and we can}
  812.       {USEVHDRs then we make the attempt to do so}
  813.  
  814.       IF ((trysuperz) OR (wantsuperz)) AND (USEVHDR) THEN
  815.         BEGIN
  816.           txhdr[zf3] := cansuperz OR canvhdr;
  817.           SendBinaryHeader(8, zfile, txhdr);
  818.         END
  819.       ELSE
  820.         SendBinaryHeader(4, zfile, txhdr);
  821.  
  822.  
  823.       SendData(txbuf, blen, zcrcw);
  824.  
  825.       REPEAT
  826.  
  827.         IF (escape) THEN
  828.           BEGIN
  829.             CanThisXfer;
  830.             Say('aborted from keyboard');
  831.             SendFile := zerror;
  832.             exit;
  833.           END;
  834.  
  835.         IF (NOT carrier) THEN
  836.           BEGIN
  837.             Say('lost carrier');
  838.             SendFile := zerror;
  839.             exit;
  840.           END;
  841.  
  842.         fillchar(rxhdr, sizeof(rxhdr), #0);
  843.         c := GetHeader(rxhdr);
  844.         ShowHdrInfo(c);
  845.         CASE c OF
  846.           zcan,
  847.           fubar,
  848.           rcdo,
  849.           ztimeout,
  850.           zfin,
  851.           fubar : BEGIN
  852.                     SendFile := zerror;
  853.                     exit
  854.                   END;
  855.  
  856.           zrinit : {loopback} ;
  857.  
  858.            zcrc : BEGIN
  859.                    PutLongInHeader(z_ckcrc32(infile));
  860.                    SendHexHeader(4, zcrc, txhdr)
  861.                  END;
  862.  
  863.           zskip : BEGIN
  864.                     SendFile := c;
  865.                     exit
  866.                   END;
  867.  
  868.  
  869.           {This rcvr header is the last flag for Super_Z transfers}
  870.           {If the rcvr has read our header correctly it }
  871.           {responds here in the zrpos header}
  872.  
  873.           zrpos : BEGIN
  874.                     IF (NOT z_seekfile(infile, rxpos)) THEN
  875.                       BEGIN
  876.                         Say('file positioning error');
  877.                         SendHexHeader(4, zferr, txhdr);
  878.                         SendFile := zerror;
  879.                         exit;
  880.                       END;
  881.  
  882.                     Say('setting start position');
  883.                     ShowFilePos(rxpos);
  884.                     strtpos := rxpos;
  885.                     txpos := rxpos;
  886.  
  887.  
  888.                     {here is our long awaited response}
  889.                     {rcvr signals Super_Z ok by placing value}
  890.                     {GOFORSUPZ in zrpos header cell "zf4"    }
  891.  
  892.                     Super_Z := ((rxhdr[zf4] AND GOFORSUPZ)<>0);
  893.  
  894.                     If Super_Z Then
  895.                       Begin
  896.                         updatewindow(szver);
  897.                         ShowTransferType(usecrc32);
  898.                       End;
  899.  
  900.                     {send the file}
  901.                     SendFile := SendFiledata;
  902.  
  903.                     exit;
  904.                   END
  905.  
  906.         END
  907.       UNTIL (c <> zrinit)
  908.  
  909.     UNTIL (done)
  910.   END;
  911.  
  912.  
  913.  
  914.  
  915. {-----------------------------------------------------------------------}
  916. (* the following routines are for the receiver side of zmodem for data *)
  917. (* and header receiving                                                *)
  918. {-----------------------------------------------------------------------}
  919.  
  920.  
  921.  
  922.  
  923.  
  924.   FUNCTION RecvData(VAR buf : buftype; buf_length : integer) : integer;
  925.   LABEL
  926.     crcfoo;
  927.   VAR
  928.     c, d, buflen    : integer;
  929.     crc     : word;
  930.     done    : boolean;
  931.   BEGIN
  932.  
  933.     Say('');
  934.  
  935.     {if we are using 32bit crc or vhdrs and 32bit crc then doit that way}
  936.  
  937.     IF (frameindicator=zbin32) OR (frameindicator=zvbin32) THEN
  938.       BEGIN
  939.         z_showtype(true);
  940.         RecvData := RecvData32(buf, buf_length);
  941.         exit;
  942.       END;
  943.  
  944.  
  945.   etc...
  946.  
  947.   END;
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954. {SendRcvrInfo is the first xmitting done to the sender from the rcvr}
  955. {We use this routine to first signal the sender that we can use}
  956. {variable headers.  This is done by placing the value CANVHDR in}
  957. {header cell zf1 of the zrinit header}
  958.  
  959. {This is where we can also see that the sender can use variable hdr}
  960. {Examine the code and you will understand the method used here.}
  961.  
  962.  
  963.  
  964.  
  965.   FUNCTION SendRcvrInfo : integer;
  966.   LABEL
  967.     again;
  968.   VAR
  969.     x, c, n, errors : integer;
  970.     ch      : char;
  971.     teststr : STRING[33];
  972.     thdr    : hdrtype;
  973.   BEGIN
  974.  
  975.     fillchar(attn, sizeof(attn), 0);
  976.     zerrors := 0;
  977.     x := 0;
  978.  
  979.     FOR n := 10 DOWNTO 0 DO
  980.       BEGIN
  981.  
  982.  
  983.         ShowHdrInfo(tryzhdrtype);
  984.  
  985.         fillchar(secbuf, sizeof(secbuf), #0);
  986.  
  987.         PutLongInHeader(longint(0));
  988.  
  989.         txhdr[zf0] := canfdx OR canovio OR canfc32 OR canbrk; {full dplx, overlay i/o and crc32}
  990.  
  991.  
  992.         {signal xmitr we can use variable headers}
  993.         txhdr[zf1] := CANVHDR;
  994.  
  995.  
  996.         {if user wants to TRYSUPERZ then we simply or CANSUPERZ}
  997.         {with header cell "zf1". Xmitr will respond with it's }
  998.         {zfile header }
  999.  
  1000.         If TRYSUPERZ Then
  1001.           Begin
  1002.             txhdr[zf1] := CANVHDR OR CANSUPERZ;
  1003.             SendHexHeader(4, tryzhdrtype, txhdr);
  1004.           End
  1005.         Else
  1006.           SendHexHeader(4, tryzhdrtype, txhdr);
  1007.  
  1008.  
  1009.         IF (tryzhdrtype = zskip) THEN
  1010.           tryzhdrtype := zrinit;
  1011.  
  1012.         again:
  1013.         IF (NOT carrier) THEN
  1014.           BEGIN
  1015.             Say('lost carrier');
  1016.             SendRcvrInfo := zerror;
  1017.             exit;
  1018.           END;
  1019.  
  1020.         IF (escape) THEN
  1021.           BEGIN
  1022.             CanThisXfer;
  1023.             Say('transfer cancelled from keyboard');
  1024.             SendRcvrInfo := zcan;
  1025.             exit;
  1026.           END;
  1027.  
  1028.  
  1029.         fillchar(rxhdr, sizeof(rxhdr), #0);
  1030.  
  1031.         c := GetHeader(rxhdr);
  1032.  
  1033.         ShowHdrInfo(c);
  1034.  
  1035.         CASE c OF
  1036.          zrqinit : BEGIN
  1037.                      {if by chance we catch the xmitrs zrqinit}
  1038.                      {header check for variable header usage}
  1039.  
  1040.                      USEVHDR := ((rxhdr[zf3] AND CANVHDR)<>0);
  1041.  
  1042.                    END;
  1043.           zfile : BEGIN
  1044.                     zconv := rxhdr[zf0];
  1045.  
  1046.                     c := RecvData(secbuf, zbuffersize);
  1047.                     ShowHdrInfo(c);
  1048.  
  1049.  
  1050.                     {if we didn't get usevhdr from the zrqinit}
  1051.                     {header try for it again now}
  1052.  
  1053.                     If (NOT USEVHDR) Then
  1054.                       USEVHDR := ((rxhdr[zf3] AND CANVHDR)<>0);
  1055.  
  1056.  
  1057.                     {if we are using variable headers then check}
  1058.                     {if xmitr has requested super_z or is responding}
  1059.                     {to our request }
  1060.  
  1061.                     If USEVHDR Then
  1062.                       Super_Z := ((rxhdr[zf3] AND CANSUPERZ) <> 0);
  1063.  
  1064.                     {we can safely say Super_Z will work so      }
  1065.                     {Super_Z will be TRUE}
  1066.  
  1067.  
  1068.                     tryzhdrtype := zrinit;
  1069.  
  1070.                     IF (c = gotcrcw) THEN
  1071.                       BEGIN
  1072.                         SendRcvrInfo := zfile;
  1073.                         exit;
  1074.                       END;
  1075.  
  1076.                     SendHexHeader(4, znak, txhdr);
  1077.                     GOTO again;
  1078.                   END;
  1079.  
  1080.           etc...
  1081.  
  1082.           {zrqinit and zfile types are all that concern us here}
  1083.  
  1084.   END;
  1085.  
  1086.  
  1087.  
  1088.  
  1089.   {this is where we tell the sender that his request for, or his}
  1090.   {response to our request is either go or nogo for Super_Z      }
  1091.  
  1092.   FUNCTION ReceiveFile : integer;
  1093.   LABEL
  1094.     err, nxthdr, moredata, baddata;
  1095.   VAR
  1096.     c, n    : integer;
  1097.     rxbytes : longint;
  1098.     sptr    : STRING;
  1099.     done    : boolean;
  1100.   BEGIN
  1101.     zerrors := 0;
  1102.     done := false;
  1103.     eofseen := false;
  1104.  
  1105.     c := GetZeroHeader;
  1106.  
  1107.     IF (c <> zok) THEN
  1108.       BEGIN
  1109.         IF (c = zskip) THEN
  1110.           tryzhdrtype := zskip;
  1111.         ReceiveFile := c;
  1112.         exit;
  1113.       END;
  1114.  
  1115.     c := zok;
  1116.     n := 10;
  1117.     rxbytes := filestart;
  1118.     rxpos := filestart;
  1119.  
  1120.     fillChar(attn,sizeof(attn),#32);
  1121.  
  1122.     PutLongInHeader(rxbytes);
  1123.  
  1124.  
  1125.     {if we have determined Super_Z is ok then flag the xmitr}
  1126.     {by placing value GOFORSUPZ in zrpos header cell "zf4"}
  1127.  
  1128.     IF Super_Z Then
  1129.       Begin
  1130.         txhdr[zf4] := GOFORSUPZ;
  1131.         SendHexHeader(8, zrpos, txhdr);
  1132.         updatewindow(SzVer);
  1133.       End
  1134.     Else
  1135.       SendHexHeader(4, zrpos, txhdr);
  1136.  
  1137.  
  1138.   etc...
  1139.  
  1140.  
  1141.  
  1142.   END;
  1143.  
  1144.  
  1145.  
  1146.  
  1147. Print out the code above and look over it.  You should be able to
  1148. translate most of what you see into your own application.
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.