home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / comm / jmodem.zip / JMODEM_C.DOC < prev    next >
Text File  |  1990-06-20  |  36KB  |  886 lines

  1.  
  2.                                   J M O D E M
  3.                          *  The Microsoft C Version  *
  4.                                  June 20, 1990
  5.                                Richard B. Johnson
  6.                               405 Broughton Drive
  7.                           Beverly Massachusetts 01915
  8.                                BBS (508) 922-3166
  9.  
  10.           Introduction.
  11.  
  12.           JMODEM was first introduced about two years ago. It has en-
  13.           joyed a steady increase in popularity around the world. It
  14.           has even been explained in some detail in John Dvorak's book
  15.           on PC communications; Dvorak's Guide to PC Telecommunica-
  16.           tions, 1990, Osborne-McGraw-Hill, 2600 Tenth Street,
  17.           Berkeley, CA.
  18.  
  19.           JMODEM was first written in assembly language. Since this
  20.           language is hard to read and use, it has been difficult for
  21.           communications program developers to incorporate it into
  22.           their programs directly. Instead it must be executed as an
  23.           external protocol. Now JMODEM has been written in the C
  24.           Language. C has become the de-facto standard for portable
  25.           code development even though there isn't presently any code
  26.           that is truly portable across many different machines. The
  27.           writing of JMODEM in C will make it easier for software de-
  28.           velopers throughout the world to use this very useful pro-
  29.           tocol.
  30.  
  31.           You can use this new version of JMODEM just as the older
  32.           versions written in assembly. It has a new color sign-on
  33.           screen and status-block windows that overlap. Although the
  34.           new JMODEM.EXE code is larger than the assembly-language
  35.           version, JMODEM.COM, the program still executes very fast
  36.           because much effort has been taken to streamline the C code.
  37.           JMODEM.COM required 64 k of RAM (one segment) to execute
  38.           properly. JMODEM.EXE requires 79 k to allow the screens to
  39.           be written properly, and 66 k of free RAM to execute without
  40.           aborting although the previous screen content will be lost.
  41.           Like all versions of JMODEM, this version is 100% compatible
  42.           with all previous version including Beta version 1.00. From
  43.           it's inception, the essential structure of JMODEM has never
  44.           been changed.
  45.  
  46.           How to install JMODEM.
  47.  
  48.           JMODEM executes best from a batch file as an external pro-
  49.           tocol for any of the communications programs that have ex-
  50.           ternal-protocol capability. A typical communications program
  51.           is TELIX.
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.                                      - 1 -
  60.                                                JMODEM, the C Version
  61.  
  62.  
  63.  
  64.           Here is a batch file used with TELIX for uploads:
  65.  
  66.           @ECHO OFF
  67.           Rem * JMODEM TELIX Upload batch file.
  68.           C:\TELIX\JMODEM S1 %3
  69.           Rem           | ||  |_________ file name (passed by TELIX)
  70.           Rem           | ||____________ COM port (1 - 4)
  71.           Rem           | |_____________ Send
  72.           Rem           |_______________ Path and name of JMODEM
  73.  
  74.  
  75.           This is a batch file used with TELIX for downloads:
  76.  
  77.           @ECHO OFF
  78.           Rem * JMODEM TELIX Download batch file.
  79.           C:\TELIX\JMODEM R1 %3
  80.           Rem           | ||  |_________ file name (passed by TELIX)
  81.           Rem           | ||____________ COM port (1 - 4)
  82.           Rem           | |_____________ Receive
  83.           Rem           |_______________ Path and name of JMODEM
  84.  
  85.  
  86.           This is a batch file used for PCPLUS (PROCOMM) uploads:
  87.  
  88.           @ECHO OFF
  89.           Rem * JMODEM PCPLUS Upload batch file.
  90.           C:\TELIX\JMODEM S1 %1
  91.           Rem           | ||  |_________ file name (passed by PCPLUS)
  92.           Rem           | ||____________ COM port (1 - 4)
  93.           Rem           | |_____________ Send
  94.           Rem           |_______________ Path and name of JMODEM
  95.  
  96.  
  97.           This is a batch file for PCPLUS (PROCOMM) ownloads:
  98.  
  99.           @ECHO OFF
  100.           Rem * JMODEM PCPLUS Download batch file.
  101.           C:\TELIX\JMODEM R1 %1
  102.           Rem           | ||  |_________ file name (passed by PCPLUS)
  103.           Rem           | ||____________ COM port (1 - 4)
  104.           Rem           | |_____________ Receive
  105.           Rem           |_______________ Path and name of JMODEM
  106.  
  107.           You can chop this text out with an editor and create your
  108.           batch files quickly and correctly. PCPLUS passes the file-
  109.           name as the %1 parameter and TELIX uses the %3 parameter.
  110.           JMODEM does not need to know anything else about your system
  111.           to operate. It does not even need to know the baud-rate or
  112.           other communications parameters. All it needs to know about
  113.           is the file name and the communications adapter port to use.
  114.  
  115.  
  116.  
  117.  
  118.                                      - 2 -
  119.                                                JMODEM, the C Version
  120.  
  121.  
  122.  
  123.           JMODEM doesn't care if you are using a 19,200 baud modem
  124.           with the DTE locked at high-speed or a 300 baud modem on a
  125.           lamp-cord. It is very smart about communications and handles
  126.           lost carriers (hangup) and flow-control in a very simple way
  127.           which will be explained in detail later.
  128.  
  129.           If you only want to try JMODEM without having to install it,
  130.           you need only to activate the JMODEM protocol on a BBS sys-
  131.           tem, then "shell to DOS" and execute it manually from the
  132.           DOS prompt. You will be pleasantly surprised at how rapidly
  133.           it can transfer a file and how well it executes over net-
  134.           works.
  135.  
  136.           How JMODEM works.
  137.  
  138.           JMODEM uses variable-length records called blocks. These
  139.           blocks start with 512 data-bytes and increase in length to a
  140.           maximum of 8192 bytes per block. There is a 6-byte overhead
  141.           associated with each block so the percentage of overhead
  142.           starts at a fairly high 0.1 percent and decreases to a very
  143.           low 0.07 percent as the transmission progresses. The block
  144.           length will increase in 512-byte increments as long as there
  145.           are no errors requiring retransmission. Should an error
  146.           occur, the block-size is cut in half. This continues until
  147.           the block-size is as short as 64 bytes.
  148.  
  149.           The blocks may actually be of any length but never exceed
  150.           the maximum allowed. An attempt is made to reduce the amount
  151.           of data that needs to be transmitted by compressing each
  152.           block before transmission. Since much data is already com-
  153.           pressed, being from ".ZIP" files and such, it is possible
  154.           that "compression" may actually cause an increase in block-
  155.           length. JMODEM will send a compressed block only if it is
  156.           shorter than the non-compressed block.
  157.  
  158.           Since it takes time to compress and expand data, only the
  159.           simplest and quickest compression method is used. It is very
  160.           effective with ".EXE" files that contain large blocks of
  161.           binary nulls and most text files but it is not very effec-
  162.           tive with highly compressed archive files. The compression
  163.           method is called "run-length-limited" or more explicitly
  164.           "how many of what kind". Basically, the block is searched
  165.           for groups if similar characters. If many similar characters
  166.           are found, compression consists of sending a sentinel byte
  167.           of hexadecimal BB, followed by a two-byte amount, and this
  168.           followed by the byte to be repeated.
  169.  
  170.           In the following example we have a string of spaces (20
  171.           hex).
  172.  
  173.  
  174.  
  175.  
  176.  
  177.                                      - 3 -
  178.                                                JMODEM, the C Version
  179.  
  180.  
  181.  
  182.           Before compression:
  183.                                ( 18 bytes )
  184.             20 20 20 20 20 20 20 20 20 20 20 34 37 87 EF FF 3A 23
  185.  
  186.  
  187.           After compression:
  188.                                ( 11 bytes )
  189.             BB 0B 00 20 34 37 87 EF FF 3A 23
  190.  
  191.           The blocks could actually get longer because the sentinel
  192.           byte could be present in the data:
  193.  
  194.           Before compression:
  195.                                ( 9 bytes )
  196.             BB 00 BB AF EF BB 00 AE EF
  197.  
  198.  
  199.           After compression:
  200.                                ( 16 bytes )
  201.             BB 01 00 BB 00 BB 01 00 BB AF BB 01 00 BB AE EF
  202.  
  203.           As soon as the encoded length exceeds the data block length,
  204.           compression is abandoned and the non-compressed block is
  205.           sent. JMODEM sends a byte that tells the receiver if the
  206.           data is compressed or not. This same byte tells the receiver
  207.           when the end-of-file has occurred so JMODEM is able to
  208.           preserve exact file-length.
  209.  
  210.                                The JMODEM block.
  211.  
  212.  
  213.           The JMODEM block looks like this:
  214.  
  215.            |< --------- First byte sent / received
  216.           20 00 01 01 .. .. .. .. .. AE 01
  217.            |  |  |  |        |        |  |___ CRC (high byte)
  218.            |  |  |  |        |        |______ CRC (low byte)
  219.            |  |  |  |        |_______________ data bytes
  220.            |  |  |  |________________________ type of block
  221.            |  |  |___________________________ block number
  222.            |  |______________________________ block length (high byte)
  223.            |_________________________________ block length (low byte)
  224.  
  225.  
  226.           The Block length:
  227.  
  228.           The block length is a WORD (16 bits). This allows the blocks
  229.           to be 65,535 bytes long although in practice the length is
  230.           not allowed to exceed 8192 bytes (plus overhead). The block-
  231.           length is the length of the entire JMODEM block, not just
  232.           the data-bytes.
  233.  
  234.  
  235.  
  236.                                      - 4 -
  237.                                                JMODEM, the C Version
  238.  
  239.  
  240.  
  241.           The Block number:
  242.  
  243.           The block number is a BYTE. It starts at 1 and becomes zero
  244.           again after block 255. It is used to make certain that all
  245.           receiption errors are detected.
  246.  
  247.           The Block type:
  248.  
  249.           This BYTE is bit-mapped to tell the receiver what kind of
  250.           block has been sent. Presently there are three kinds of
  251.           blocks:
  252.  
  253.                 00000000B       Hex 00  ( Normal data )
  254.                 00000001B       Hex 01  ( Compressed data )
  255.                 00000010B       Hex 02  ( End of file )
  256.  
  257.           The CRC:
  258.  
  259.           The CRC is a WORD (16 bits). It is not a "standard" type of
  260.           CRC because, unless done with hardware, a standard 16-bit
  261.           polynomial would take several seconds to calculate for a
  262.           long block. Instead it uses a rapid rotate and sum algorithm
  263.           that is probably just as effective as the more "standard"
  264.           polynomials.
  265.  
  266.           The CRC is generated using this polynomial:
  267.  
  268.           X =  X + X^(2(n-mod 7)).......  Where n = t(n-1)
  269.                                          And t = string length
  270.  
  271.           It has the advantage of simplicity in assembly-language
  272.           programming and will detect errors with a probability of
  273.           about  one undetected error in 2^132 (which is a very large
  274.           number). It does not correct errors so its not important to
  275.           use some "standard" function to generate the CRC.
  276.  
  277.           The C code shows how easy it is to create and check this
  278.           kind of CRC.
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294.  
  295.                                      - 5 -
  296.                                                JMODEM, the C Version
  297.  
  298.  
  299.                            The JMODEM Communications
  300.                                 Hardware Control
  301.  
  302.           When JMODEM is first loaded for execution it checks the
  303.           state of the modem-control leads. If there is no modem
  304.           carrier detected, it assumes that you have connected two PCs
  305.           together without a modem and will not bother to check for a
  306.           dropped carrier during execution.
  307.  
  308.           Since JMODEM must exercise flow-control so it can be used
  309.           with high-speed modems with fixed baud rates, it also as-
  310.           sumes that at the time at which it is first executed, the
  311.           modem will be requesting data because there will have been
  312.           very little I/O over the previous few seconds. JMODEM stores
  313.           the state of RTS/CTS and DTR/DSR and uses this as a refer-
  314.           ence. When transmitting data, should JMODEM find that the
  315.           state of these modem-control leads has changed, it waits
  316.           until the modem-control leads have reverted back to the
  317.           initial state before sending any more data. This allows ANY
  318.           modem to exercise flow-control with JMODEM, even those that
  319.           use "pin 4" instead of "pin 20". When JMODEM is waiting, it
  320.           checks to verify that the modem carrier has not been drop-
  321.           ped. If the carrier is dropped, or if the user aborts,
  322.           JMODEM will exit, setting a DOS ERRORLEVEL code.
  323.  
  324.           You can abort JMODEM at any time by hitting Ctrl-Break or
  325.           Ctrl-C. It will take several seconds for JMODEM to abort
  326.           because it does not continually check these keys. Unlike
  327.           previous versions, JMODEM erases the files from aborted
  328.           downloads. Also, JMODEM will abort if it is unable to rename
  329.           a file in the following example.
  330.  
  331.           Suppose you wish to download a file called VIRUS.EXE. Sup-
  332.           pose also that VIRUS.EXE already exists. Instead of over-
  333.           writing your previous version of VIRUS.EXE, JMODEM has al-
  334.           ways been nice and renamed it to VIRUS.OLD before creating a
  335.           new file. With previous versions of JMODEM, if VIRUS.OLD
  336.           already existed, JMODEM would have deleted it before renam-
  337.           ing the present file to ".OLD". This no longer is done.
  338.           JMODEM never deletes ANYTHING anymore except it's own abort-
  339.           ed download. This should reduce the number of threats I have
  340.           received!
  341.  
  342.  
  343.  
  344.  
  345.  
  346.  
  347.  
  348.  
  349.  
  350.  
  351.  
  352.  
  353.  
  354.                                      - 6 -
  355.                                                JMODEM, the C Version
  356.  
  357.  
  358.                                The C programmer's
  359.                                 Guide to JMODEM
  360.  
  361.           Included within this package should be the following files:
  362.           JMODEM         This is a Microsoft MAKE file for JMODEM.EXE.
  363.           JMODEMTC       Borland's Turbo C MAKE file for JMODEM.EXE.
  364.           JMODEM    EXE  The executable file
  365.           JMODEMTC  RSP  Link response file for Borland's Turbo C
  366.           JMODEM_A  C    Contains the _main() routine entry point.
  367.           JMODEM_B  C    Allocates memory, parses input strings.
  368.           JMODEM_C  C    All of the file I/O is in this file.
  369.           JMODEM_D  C    Data compression/expansion, CRC calculation
  370.           JMODEM_E  C    Communications I/O interrupt service, etc.
  371.           JMODEM_F  C    Screen I/O (windows, etc)
  372.           JMODEM    H    Contains JMODEM globals and data structures.
  373.           SCREEN    H    Screen definitions, prototypes, structures
  374.           UART      H    Definitions for the 8250 UART
  375.           TEST      C    This tests compression /expansion, disk I/O.
  376.           TEST           This is the Microsoft MAKE file for TEST.EXE
  377.           TESTTC         Borland's Turbo C MAKE file for TEST.EXE
  378.           SHOW      C    Source for verifying execution in a DOS shell
  379.           SHOW           Microsoft MAKE file for SHOW.EXE
  380.           SHOWTC         Borland's Turbo C MAKE file for SHOW.EXE
  381.           SHOW      EXE  Executes JMODEM from a DOS shell.
  382.           TEST      C    Tests JMODEM data-compression and file I/O.
  383.           TEST           Microsoft MAKE file for TEST.EXE
  384.           TESTTC         Borland's Turbo C MAKE file for TEST.EXE
  385.           TEST      EXE  Executable to test file I/O and compression
  386.  
  387.           If you have MicroSoft 'C' version 5.0 or later, and if your
  388.           environment and paths are properly set up, you should be
  389.           able to type:
  390.  
  391.                 MAKE JMODEM
  392.                 ... and a brand new version of JMODEM will be created.
  393.  
  394.           If you use Borland's Turbo C, you can use the "TC" make
  395.           files to do the same.
  396.  
  397.           Brad Smith from Jacksonville North Carolina created the MAKE
  398.           files for Turbo C and modified the source-code to accommo-
  399.           date the different libraries used in Turbo C. His revisions
  400.           will be present in all subsequent versions of JMODEM to
  401.           assure compatibility with Borland's Turbo C.
  402.  
  403.           Brad is a Turbo C guru and runs a BBS system in
  404.           Jacksonville.
  405.  
  406.                 Brad Smith
  407.                 141 Riggs Street
  408.                 Jacksonville, North Carolina 28540
  409.  
  410.  
  411.  
  412.  
  413.                                      - 7 -
  414.                                                JMODEM, the C Version
  415.  
  416.  
  417.                 BBS (919) 455-5972 12/24/9600+ 24 hrs
  418.  
  419.           With this release, there seems to be a Null-Pointer
  420.           assignment error when using Borland's Small Model in TCC
  421.           Version 1.5. This is a compiler bug, or more specifically a
  422.           bug in the C0.ASM code provided with the compiler that you
  423.           can fix.
  424.  
  425.           If you are a Turbo C programmer, don't use the small model
  426.           when creating JMODEM.EXE unless you repair the C0.ASM file
  427.           and create a new C0S.OBJ file using the MAKE-C0.BAT file
  428.           that is provided with the compiler.
  429.  
  430.  
  431.           To fix the null-pointer problem in Turbo-C find the
  432.           following code-fragment in \LIB\C0.ASM provided with your
  433.           compiler:
  434.  
  435.  
  436.           IFNDEF        __HUGE__
  437.  
  438.           ;     Reset un-initialized datas
  439.  
  440.                         xor     ax, ax
  441.                         mov     es, cs:DGROUP@@
  442.                         mov     di, offset DGROUP: bdata@
  443.                         mov     cx, offset DGROUP: edata@
  444.                         sub     cx, di
  445.                 rep     stosb
  446.           ENDIF
  447.  
  448.           Add the following code:
  449.  
  450.                 push    ds
  451.                 mov     ax,DGROUP
  452.                 mov     ds,ax
  453.                 mov     word ptr ds:[0],0
  454.                 pop     ds
  455.  
  456.  
  457.           Now find this next code-fragment:
  458.  
  459.                         xor     ax, ax
  460.                         mov     si, ax
  461.                         mov     cx, lgth_CopyRight
  462.                         cld
  463.           ComputeChecksum label near
  464.                         add     al, [si]
  465.                         adc     ah, 0
  466.                         inc     si
  467.                         loop    ComputeChecksum
  468.  
  469.  
  470.  
  471.  
  472.                                      - 8 -
  473.                                                JMODEM, the C Version
  474.  
  475.  
  476.                         sub     ax, CheckSum
  477.                         jz      ExitToDOS
  478.                         mov     cx, lgth_NullCheck
  479.                         mov     dx, offset DGROUP: NullCheck
  480.                         call    ErrorDisplay
  481.  
  482.           Modify the code so it looks like this:
  483.  
  484.           ;             xor     ax, ax
  485.           ;             mov     si, ax
  486.           ;             mov     cx, lgth_CopyRight
  487.           ;             cld
  488.           ;ComputeChecksum label        near
  489.           ;             add     al, [si]
  490.           ;             adc     ah, 0
  491.           ;             inc     si
  492.           ;             loop    ComputeChecksum
  493.           ;             sub     ax, CheckSum
  494.  
  495.                 push    ds
  496.                 mov     ax,DGROUP
  497.                 mov     ds,ax
  498.                 cmp     word ptr ds:[0],0
  499.                 pop     ds
  500.  
  501.                         jz      ExitToDOS
  502.                         mov     cx, lgth_NullCheck
  503.                         mov     dx, offset DGROUP: NullCheck
  504.                         call    ErrorDisplay
  505.  
  506.  
  507.           After to have done this, execute MAKE-C0.BAT for the small
  508.           model library from the DOS prompt:
  509.  
  510.           F:\TURBOC\LIB> MAKE-C0 SMALL
  511.  
  512.           This will create a new small-model startup object file.
  513.  
  514.           Just as in the MASM language files, the source code is
  515.           strongly-typed. All function prototypes are declared and no
  516.           defaults are used. You can compile at warning-level 3, the
  517.           most stringent level available with Microsoft compilers, and
  518.           you will get no warning errors at all. The default warning
  519.           level with Borland's compiler is even more stringent. You
  520.           will get a single warning error when compiling TEST.C as the
  521.           compiler discovers that dummy parameter "one" in the dummy
  522.           screen routine isn't used at all. It has been my experience
  523.           that if you get any warnings (in real code), they MUST be
  524.           fixed or they will bite you later on.
  525.  
  526.           Example:
  527.  
  528.  
  529.  
  530.  
  531.                                      - 9 -
  532.                                                JMODEM, the C Version
  533.  
  534.  
  535.                         *memory++ = foo;
  536.                 ... will bump the memory pointer after you put foo
  537.                 into memory. Suppose you get to the end of the block
  538.                 and wish to index backwards.
  539.  
  540.                 Do you use ...
  541.                         --*memory = foo;
  542.                 ...?
  543.  
  544.                 You do NOT!! You must use:
  545.  
  546.                         *(--memory) = foo;
  547.  
  548.           Little things like this (this is a BIG, BIG bug), could
  549.           cause code to work <sometimes> and keep you awake nights.
  550.           JMODEM has been carefully written to prevent bugs like this.
  551.           It is impossible to be sure that there are no bugs in even
  552.           simple code so be careful if you modify the source.
  553.  
  554.           You may modify JMODEM for your own use, but  P L E A S E  do
  555.           NOT distribute the modified version on BBS systems because I
  556.           do not wish to support 222,500 versions of JMODEM! If you
  557.           find a bug, or wish to improve or add something that will
  558.           increase the value of JMODEM without making it incompatible
  559.           with previous versions, please upload your improvements to
  560.           my BBS system and I may include the revisions (with your
  561.           name attached) in an upcoming version. Note that there are 6
  562.           "type" bits available in the JMODEM control-byte that could
  563.           be used to tell the receiver that another file is coming,
  564.           etc., (for batch). Things like this could be added without
  565.           destroying compatibility with previous versions.
  566.  
  567.           MicroSoft C seems to have several bugs one of which affects
  568.           files that are very long (over 256k). My first attempts to
  569.           use C files under MicroSoft for JMODEM used the stream-I/O
  570.           (FILE *) type of files. This resulted in corruption of long
  571.           files. Therefore I implemented the UNIX/DOS type of file-I/O
  572.           that uses handles rather than file-control blocks. These
  573.           work rather well.
  574.  
  575.           Starting with Version V3.06, The JMODEM distribution file
  576.           will no longer contain the old JMODEM.ASM source. This is to
  577.           reduce the download time. The C version is now mature enough
  578.           so that there is little or no difference between the per-
  579.           formance of JMODEM.COM, the assembly version, and
  580.           JMODEM.EXE, the C version. The original C version was about
  581.           25 k in length. It is now only about 12.
  582.  
  583.           Floating point:
  584.  
  585.           Originally no floating-point libraries were used. The de-
  586.           fault is still not to use any because they result in doubl-
  587.  
  588.  
  589.  
  590.                                      - 10 -
  591.                                                JMODEM, the C Version
  592.  
  593.  
  594.           ing the size of the code. Some persons have complained that
  595.           the speed (cps) indication is not very accurate. This is
  596.           true because of the granularity of the time returned from
  597.           DOS (one second). If you add /DFTIME to the command-line
  598.           used to compile JMODEM_A.C in the "MAKE" file, the compiler
  599.           will use floating-point routines for the speed calculation.
  600.           The resulting JMODEM.EXE will be about 35k in length,
  601.           though, so this is a trade-off. If you wish accurate timing,
  602.           you pay for it in much-increased code-size.
  603.  
  604.           Modems:
  605.  
  606.           When JMODEM gets control, it turns ON CTS and DSR just in
  607.           case the BBS program has turned them off (WILDCAT does).
  608.           Some modems "hiccup" when this occurs, and the RTS line will
  609.           bounce. This caused JMODEM to "wait forever" for a RTS that
  610.           never occurs. Therefore I added a 1/2 second delay between
  611.           the time that I first set these bits and the time I start
  612.           checking for RTS and RLSD for flow-control and a possible
  613.           abort. This fixed this problem. The flow-control problem is
  614.           complex because user's might wish to transfer files between
  615.           two computers using only three wires. In such a case, there
  616.           is no flow-control and there is no modem carrier. To accom-
  617.           modate a universal solution to various hookups, JMODEM
  618.           checks for the state of DSR/CTS and RLSD when it first gets
  619.           control. If there is no carrier at this time, JMODEM will
  620.           not check for an aborted carrier during transmission or
  621.           reception. If JMODEM detects a CHANGE in either DSR or CTS,
  622.           it assumes this is flow-control and waits for these bits to
  623.           change back to whatever they were when JMODEM first obtained
  624.           control. This protocol has been used successfully since the
  625.           very first version of JMODEM. There is, however, a pos-
  626.           sibility of JMODEM wrongly interpreting what it finds if
  627.           there is "bounce" when it first gets control. That's the
  628.           reason for the delay. In any event, the normal "timeout"
  629.           trap will prevent a hung system.
  630.  
  631.           BBS systems:
  632.  
  633.           JMODEM still gets blamed for crashing some BBS systems even
  634.           though it is not JMODEM's fault. A common problem occurs
  635.           with systems that use compiled BASIC. Some BBS system pro-
  636.           grams assume certain characteristics about external proto-
  637.           cols and will blow up when the assumption is wrong. If you
  638.           use BASIC code that works like this:
  639.  
  640.                 PROTOSEND$ = "JMODEM S1 "
  641.                 COMSTRING$ = PROTOSEND$+FILENAME$
  642.  
  643.                 SHELL COMSTRING$
  644.  
  645.  
  646.  
  647.  
  648.  
  649.                                      - 11 -
  650.                                                JMODEM, the C Version
  651.  
  652.  
  653.                 ... Then JMODEM (and other protocols) will work okay.
  654.  
  655.           However, If you attempt to BLOAD, CALL, or CHAIN to it, the
  656.           results will be indeterminate. This is because JMODEM
  657.           allocates memory from C runtime routines that get their
  658.           memory from DOS (not BASIC). BASIC will not "know" that its
  659.           memory has been used by the external protocol. If you exe-
  660.           cute the "SHELL" command, then you force BASIC to give up
  661.           all the memory that it can afford to spare. This free memory
  662.           is recorded by DOS and can be used for the external proto-
  663.           col.
  664.  
  665.           BBS systems written is C should execute external protocols
  666.           something like this:
  667.  
  668.                 strcpy(command_line,"JMODEM S1 FILENAME");
  669.                 system (command_line);
  670.  
  671.           The C "system" command executes DOS commands from within C
  672.           programs by freeing memory and then executing COMMAND.COM.
  673.           Some C compilers don't have to load an aditional copy of
  674.           COMMAND.COM. They use an undocumented "back-door" to the
  675.           existing command interpreter! This saves memory.
  676.  
  677.           This is a sneak preview of the undocumented procedure:
  678.  
  679.           MOV   WORD PTR [SP_SAV],SP    ; Put the SP in a safe place
  680.           MOV   WORD PTR [SS_SAV],SS    ; Save segment registers.
  681.           MOV   WORD PTR [DS_SAV],DS
  682.           MOV   WORD PTR [ES_SAV],ES
  683.           MOV   AX,4A00H                ; Free memory
  684.           MOV   BX,OFFSET TOP           ; Point to the top of code
  685.           MOV   CL,4                    ; Bits to shift
  686.           SHR   BX,CL                   ; Div / 16
  687.           INC   BX                      ; Round up
  688.           INT   21H                     ; Free some memory
  689.           ;
  690.           MOV   SI,OFFSET COMMAND       ; Point to the command
  691.           INT   2EH                     ; Make the undocumented call
  692.           CLI                           ; No interrupts, cleaning up
  693.           MOV   DS,WORD PTR CS:[DS_SAV] ; Restore all segments
  694.           MOV   ES,WORD PTR [DS_SAV]
  695.           MOV   SS,WORD PTR [SS_SAV]
  696.           MOV   SP,WORD PTR [SP_SAV]    ; Restore stack pointer
  697.           STI                           ; Allow interrupts
  698.  
  699.           If JMODEM and other external protocols are executed from BBS
  700.           software in this manner, then you will have no problems.
  701.           JMODEM preserves the BBS system communications environment
  702.           so BBS systems don't have to reinitialize anything when they
  703.           get control. JMODEM does not even touch the baud rate! Its
  704.  
  705.  
  706.  
  707.  
  708.                                      - 12 -
  709.                                                JMODEM, the C Version
  710.  
  711.  
  712.           not necessary to alter any communications parameters so it
  713.           doesn't.
  714.  
  715.           A small program, SHOW.C is provided with this distribution.
  716.           It is a C program that allocates a lot of memory, writes to
  717.           the memory, then executes JMODEM.EXE using the "system"
  718.           command. After JMODEM returns from the shell, SHOW then
  719.           continues to write to memory before exiting. Since this
  720.           procedure is properly written, no system crash will occur.
  721.           You can load multiple copies of COMMAND.COM to "eat" memory.
  722.           Eventually there will be too little memory available for
  723.           JMODEM to execute. The system will still not crash.
  724.  
  725.           Help:
  726.  
  727.           JMODEM is now over three years old. I first wrote it in
  728.           assembly and slowly it caught on. I spent last Christmas
  729.           writing it in C. Since the C release, I have received over
  730.           500 comments from persons telling me how to make it better.
  731.           Most of these comments were from so-called professional
  732.           programmers who complained about various things. A synopsis
  733.           follows:
  734.  
  735.           "It should have been written UNIX-style..."
  736.           "It has too many comments and they don't make any sense..."
  737.           "The usage prompt should read: jmodem <r|s><port> filespec."
  738.           "It breaks my modem..."
  739.           "It is full of bugs which I have had to fix ..." (BBS sysop)
  740.           "It destroys my operating system..."
  741.           "It does not work..." (BBS sysop)
  742.           "I have never before seen such trash..." (College professor)
  743.           "It is very poorly written..." (Professional programmer)
  744.           "You are not handling interrupts correctly..."
  745.           "The MAKE file is amateurish..." (Professional programmer)
  746.           "You should not use pointers..." (Professional programmer)
  747.           "You don't use enough pointers..." (Professional programmer)
  748.           "You don't use pointers correctly..." (College instructor)
  749.           "You can't cast pointers to anything you like..."
  750.           "Microsoft C is not a professional C ..."
  751.           "You must never chain to the timer interrupt..."
  752.           "You will lose interrupts when you send 0x20 to the
  753.           controller..."
  754.           "You must check the UART status in the interrupt service
  755.           routine..." (Programmer at DIGITAL)
  756.           etc., etc...
  757.  
  758.           There were no such comments when only the assembly-language
  759.           version existed. You see, few know how to read assembly-
  760.           language. It seems that  E V E R Y B O D Y  is expert in C.
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.                                      - 13 -
  768.                                                JMODEM, the C Version
  769.  
  770.  
  771.           I would like to answer each comment individually but don't
  772.           have the time. I'm busy writing an advanced operating system
  773.           at work. You see, I am a professional too.
  774.  
  775.           If this seems too editorial, you haven't read anything yet!
  776.           There are just too many persons who think they know every-
  777.           thing there is to know about anything that comes along when,
  778.           in fact, they know very little about their claimed field of
  779.           expertise. For instance, one programmer "fixed" the UART
  780.           transmit routine by enabling FIFO buffering on special
  781.           UARTs. If we can assume that this "fix" won't hurt generic
  782.           8250 devices, what does it accomplish? The transmitter
  783.           operates polled because it can't do anything else until it
  784.           receives an ACK or NAK from the receiving party. Just think,
  785.           all the MIPS of your processor is sitting there waiting for
  786.           the UART to become ready to receive another byte! There is
  787.           nothing, absolutely nothing that you can do to make the UART
  788.           transmit faster than the baud-rate. Enabling FIFO buffering
  789.           on special UARTs may help maintain the baud-rate speed on
  790.           interrupt driven systems with a high interrupt-latency time
  791.           (multitasking systems). It can't do a thing for us with our
  792.           clones and terminal programs.
  793.  
  794.           In the case of checking the UART status in the interrupt
  795.           service routine, why?? The UART is enabled to interrupt only
  796.           when a received byte is available. The program would not be
  797.           executing the interrupt-service routine if a byte was not
  798.           available so why check again? Just get the byte, put it in
  799.           the buffer and get out as quickly as you can. That is what
  800.           an interrupt service routine is supposed to do.
  801.  
  802.           In spite of this, I welcome useful comments and enhancements
  803.           to JMODEM. Just make the revision and upload it to my BBS.
  804.           If I use the revision, you will be credited for your help.
  805.           Please remember that an enhancement is not a "preference".
  806.           If you prefer to do something one way or another then feel
  807.           free to modify the code for your own use. If you find a
  808.           better way to do something then please let me know.
  809.  
  810.  
  811.  
  812.  
  813.  
  814.  
  815.  
  816.  
  817.  
  818.  
  819.  
  820.  
  821.  
  822.  
  823.  
  824.  
  825.  
  826.                                      - 14 -
  827.                                                JMODEM, the C Version
  828.  
  829.  
  830.                             JMODEM revision history
  831.  
  832.           The revision history has been moved to JMODEM_A.C and to
  833.           JMODEM.H (identical copies). This makes it easier to keep
  834.           the documentation current.
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.  
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.  
  868.  
  869.  
  870.  
  871.  
  872.  
  873.  
  874.  
  875.  
  876.  
  877.  
  878.  
  879.  
  880.  
  881.  
  882.  
  883.  
  884.  
  885.                                      - 15 -
  886.