Category : Communication (modem) tools and utilities
Archive   : JMODM311.ZIP
Filename : JMODEM_C.XYW

 
Output of file : JMODEM_C.XYW contained in archive : JMODM311.ZIP
®LM10¯®RM70¯®FC¯
J M O D E M
* The Microsoft C Version *
®DA¯
Richard B. Johnson
405 Broughton Drive
Beverly Massachusetts 01915
BBS (508) 922-3166
®FL¯®RFA®FC¯- ®PN¯ -
®FL¯¯®RHA®FR¯JMODEM, the C Version ®PG¯
®FL¯

¯
Introduction.

JMODEM was first introduced about two years ago. It has en~joyed a steady increase in popularity around the world. It has even been explained in some detail in John Dvorak's book on PC communications; Dvorak's Guide to PC Telecommunica~tions, 1990, Osborne-McGraw-Hill, 2600 Tenth Street, Berkeley, CA.

JMODEM was first written in assembly language. Since this language is hard to read and use, it has been difficult for communications program developers to incorporate it into their programs directly. Instead it must be executed as an external protocol. Now JMODEM has been written in the C Language. C has become the de-facto standard for portable code development even though there isn't presently any code that is truly portable across many different machines. The writing of JMODEM in C will make it easier for software de~velopers throughout the world to use this very useful pro~tocol.

You can use this new version of JMODEM just as the older versions written in assembly. It has a new color sign-on screen and status-block windows that overlap. Although the new JMODEM.EXE code is larger than the assembly-language version, JMODEM.COM, the program still executes very fast because much effort has been taken to streamline the C code. JMODEM.COM required 64 k of RAM (one segment) to execute properly. JMODEM.EXE requires 79 k to allow the screens to be written properly, and 66 k of free RAM to execute without aborting although the previous screen content will be lost. Like all versions of JMODEM, this version is 100% compatible with all previous version including Beta version 1.00. From it's inception, the essential structure of JMODEM has never been changed.

How to install JMODEM.

JMODEM executes best from a batch file as an external pro~tocol for any of the communications programs that have ex~ternal-protocol capability. A typical communications program is TELIX.
®NB¯
Here is a batch file used with TELIX for uploads:

@ECHO OFF
Rem * JMODEM TELIX Upload batch file.
C:\TELIX\JMODEM S1 %3
Rem | || |_________ file name (passed by TELIX)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Send
Rem |_______________ Path and name of JMODEM
®BB¯
®NB¯
This is a batch file used with TELIX for downloads:

@ECHO OFF
Rem * JMODEM TELIX Download batch file.
C:\TELIX\JMODEM R1 %3
Rem | || |_________ file name (passed by TELIX)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Receive
Rem |_______________ Path and name of JMODEM
®BB¯
®NB¯
This is a batch file used for PCPLUS (PROCOMM) uploads:

@ECHO OFF
Rem * JMODEM PCPLUS Upload batch file.
C:\TELIX\JMODEM S1 %1
Rem | || |_________ file name (passed by PCPLUS)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Send
Rem |_______________ Path and name of JMODEM
®BB¯
®NB¯
This is a batch file for PCPLUS (PROCOMM) ownloads:

@ECHO OFF
Rem * JMODEM PCPLUS Download batch file.
C:\TELIX\JMODEM R1 %1
Rem | || |_________ file name (passed by PCPLUS)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Receive
Rem |_______________ Path and name of JMODEM
®PG¯
If I wished to receive in the "batch" mode, I could make a file like this. Notice that some communications programs do not allow multiple file names. Note that the comments "!" are NOT ALLOWED in a DOS batch file.

:DO_LOOP ! Return here
IF "%3" == "" GOTO DONE ! More parameters?
C:\TELIX\JMODEM R1 %3 ! Execute JMODEM
IF ERRORLEVEL 1 GOTO DONE ! Abort on error
SHIFT ! %4 becomes %3
GOTO DO_LOOP ! Continue
:DONE ! Exit batch file

If you do not know what "%" parameters are used to pass the file name, all you have to do is make a "dummy" batch file that contains the following:

@ECHO OFF
ECHO %1
ECHO %2
ECHO %3
ECHO %4
ECHO %5
PAUSE

When this is executed, you will see something like this:

1200
1
FILENAME.TYP
ECHO is off
ECHO is off
Strike a key when ready . . .

The first line contains "1200" which is the baud rate. This means that the %1 parameter contains the baud rate.

The second line contains "1" which is the communications adapter port being used. This means that the port is being passed as the %2 parameter.

The third line contains "FILENAME.TYP" which is the file name. This means that the file name is being passed as the %3 parameter.

The fourth and fifth lines contain nothing to echo so DOS replies the current state of the echo function which is "off".

PCPLUS handles the file name passing a little bit different. If I execute the same "dummy" batch file from the PCPLUS directory, the response is:

FILENAME.TYP
ECHO is off
ECHO is off
ECHO is off
ECHO is off
Strike a key when ready . . .

This shows us that PCPLUS passes the file name as the first parameter and there are no other parameters. However, If I put more parameters on the command line within PCPLUS, they will get sent to the batch file. The response is:

FILENAME.001
FILENAME.002
FILENAME.003
FILENAME.
ECHO is off
Strike a key when ready . . .

Therefore PCPLUS allows up to four file names to be passed providing there's room on the command line.

Notice that these two communications programs check the default directory for the external protocol batch file FIRST! Therefore you must make certain that there are no other similarly-named batch files in the current directory or within the current path. Failure to do so will cause the improper execution of the wrong batch file. Lets say that the path was "C:\DOS;C:\TOOLS;C:\PCPLUS;C:\TELIX;C:\QMODEM". If you named all your JMODEM external protocol batch files with the same name, and you were attempting to use an ex~ternal file transfer protocol from QMODEM, the batch file designed to operate with PCPLUS would be the first one "found" and executed since the search-path will search the \PCPLUS directory before the \QMODEM directory. You prevent the execution of the incorrect batch file by calling them slightly different names.

When setting up external protocols, remember to configure the communications program so that it prompts you for the file names. Unlike some protocols, JMODEM does not transfer the file name. You can use any file name that you wish. You must pass the file name to JMODEM since it must know the name of the file being transmitted or received. There are no defaults.

Version V3.09 adds support for absolute port addresses and IRQ numbers. This allows one to use multiple boards that use strange ports and interrupt levels. This also allows one to thoroughly screw up his system by writing to the wrong ports by accident. JMODEM now accepts:

JMODEM R(3F8:4) filename.typ

... for an input string as well as the generic port number. In this case, "3F8" is the hexadecimal port address and "4" is the IRQ number. The delimiters are required. Be very careful when using this new feature. Writes to incor~rect port addresses can destroy the contents of hard disks, etc. JMODEM has no way of "knowing" if you give it the wrong address to use. The complete input specification for the new feature is:

JMODEM R(2F8:3) filename.typ
| | | |____________ filename
| | |_______________ IRQ to use
| |_________________ hex port address
|_____________________ Receive.

JMODEM S(2F8:3) filename.typ
| | | |____________ filename
| | |_______________ IRQ to use
| |_________________ hex port address
|_____________________ Send.

There must be no spaces between the "X(YYY:Z)" syntax. This means that if your batch file gets its parameters from an environment variable, it must be parsed like this:

JMODEM S(%PORT%:%IRQ%) %3

In this case, the two environment variables would have been declared using the DOS "SET" command like:

C:\> SET PORT=3F8
C:\> SET IRQ=4

There must be no spaces between the "=" and the varable.

®PG¯
®FC¯Setting up a BBS System
External File-Transfer Protocol.
®FL¯

If you are running a WILDCAT! bulletin board, the external protocol files can be set up like this:

(JUP.BAT)
CD D:\WILDCAT\PROTOCOL
IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
JMODEM R1 %3
IF ERRORLEVEL 1 GOTO END
COPY %3 %4
:END
DEL %3

(JDOWN.BAT)
CD D:\WILDCAT\PROTOCOL
IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
JMODEM S1 %3
IF ERRORLEVEL 1 GOTO BAD
GOTO END
:BAD
COPY ALL.OK TRANSFER.BAD
:END

There are many variations available. Since WILDCAT! supports batch-mode downloading, you could set up the batch file like this:

(JDOWN.BAT)
CD D:\WILDCAT\PROTOCOL
IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
:DO_LOOP
IF "%3" == "" GOTO END
JMODEM S1 %3
IF ERRORLEVEL 1 GOTO BAD
SHIFT
GOTO DO_LOOP
:BAD
COPY ALL.OK TRANSFER.BAD
:END

WILDCAT! checks the \PROTOCOL directory to see if the file TRANSFER.BAD has been created. If it exists, it announces that the file transfer has failed. It also announces "Error with external protocol .. ". It does this when, in fact, WILDCAT! has made an error itself. In many cases WILDCAT! will "find" the file TRANSFER.BAD when it DOES NOT EXIST! In spite of this bug, WILDCAT! is one of the most reliable BBS systems supporting external protocols.

When setting up batch files remember that there is also a bug in all DOS versions. The "IF ERRORLEVEL " statement does NOT test the actual value of ERRORLEVEL! Instead it checks to see if the returned value is EQUAL or GREATER than the tested value. If you were to put the statement:

IF ERRORLEVEL 0 GOTO GOOD

.... in a batch file, the execution would ALWAYS branch to label "GOOD" regardless of the actual ERRORLEVEL returned!

JMODEM does not require any information about handshaking. It will look at the modem port and figure out for itself what to do.

In the event that the modem carrier is lost, JMODEM will abort. Since JMODEM only checks the modem port occasionally, it may take several seconds to abort when the carrier is lost. It is impossible for a user to get at the DOS level through JMODEM. Do NOT use the CTTY command in the external protocol batch files. JMODEM returns ERRORLEVEL 1 if there was any error in transmission or reception. It returns ERRORLEVEL 0 (no error) otherwise. It does not delete files that have been partially received although it properly clos~es them. The system operator can arrange the batch files to delete them if required.

When JMODEM attempts to create a file that already exists it can't ask the user if the old one should be deleted since the user is probably not in a terminal program at the time. Therefore, JMODEM renames the other file to and creates the new file. In the event that exists, it is deleted before the rename operation occurs.

If you don't know what parameters are being sent to external protocols, you can make a dummy batch file to check them using the DOS's echo command just as explained in the user interface previous to this "BBS" section. You can't see the parameters being echoed from a remote terminal. You must be present at the BBS board terminal to test those parameters unless you modify the dummy command file like this:

@ECHO OFF
ECHO %1>COM1
ECHO %2>COM1
ECHO %3>COM1
ECHO %4>COM1
ECHO %5>COM1

If you find that your system passes the file name as %3, your "upload" (receive) batch file would contain this:

JMODEM R1 %3

Your "download" (send) batch file would contain this:

JMODEM S1 %3

In these examples, it is assumed that you are using communications adapter port "1".

You can chop this text out with an editor and create your batch files quickly and correctly. PCPLUS passes the file-name as the %1 parameter and TELIX uses the %3 parameter. JMODEM does not need to know anything else about your system to operate. It does not even need to know the baud-rate or other communications parameters. All it needs to know about is the file name and the communications adapter port to use.

JMODEM doesn't care if you are using a 19,200 baud modem with the DTE locked at high-speed or a 300 baud modem on a lamp-cord. It is very smart about communications and handles lost carriers (hangup) and flow-control in a very simple way which will be explained in detail later.

If you only want to try JMODEM without having to install it, you need only to activate the JMODEM protocol on a BBS sys~tem, then "shell to DOS" and execute it manually from the DOS prompt. You will be pleasantly surprised at how rapidly it can transfer a file and how well it executes over net~works.

How JMODEM works.

JMODEM uses variable-length records called blocks. These blocks start with 512 data-bytes and increase in length to a maximum of 8192 bytes per block. There is a 6-byte overhead associated with each block so the percentage of overhead starts at a fairly high 0.1 percent and decreases to a very low 0.07 percent as the transmission progresses. The block length will increase in 512-byte increments as long as there are no errors requiring retransmission. Should an error occur, the block-size is cut in half. This continues until the block-size is as short as 64 bytes.

The blocks may actually be of any length but never exceed the maximum allowed. An attempt is made to reduce the amount of data that needs to be transmitted by compressing each block before transmission. Since much data is already com~pressed, being from ".ZIP" files and such, it is possible that "compression" may actually cause an increase in block-length. JMODEM will send a compressed block only if it is shorter than the non-compressed block.

Since it takes time to compress and expand data, only the simplest and quickest compression method is used. It is very effective with ".EXE" files that contain large blocks of binary nulls and most text files but it is not very effec~tive with highly compressed archive files. The compression method is called "run-length-limited" or more explicitly "how many of what kind". Basically, the block is searched for groups if similar characters. If many similar characters are found, compression consists of sending a sentinel byte of hexadecimal BB, followed by a two-byte amount, and this followed by the byte to be repeated.

In the following example we have a string of spaces (20 hex).
®NB¯
Before compression:
( 18 bytes )
20 20 20 20 20 20 20 20 20 20 20 34 37 87 EF FF 3A 23
®BB¯
®NB¯
After compression:
( 11 bytes )
BB 0B 00 20 34 37 87 EF FF 3A 23
®BB¯
The blocks could actually get longer because the sentinel byte could be present in the data:
®NB¯
Before compression:
( 9 bytes )
BB 00 BB AF EF BB 00 AE EF
®BB¯
®NB¯
After compression:
( 16 bytes )
BB 01 00 BB 00 BB 01 00 BB AF BB 01 00 BB AE EF
®BB¯
As soon as the encoded length exceeds the data block length, compression is abandoned and the non-compressed block is sent. JMODEM sends a byte that tells the receiver if the data is compressed or not. This same byte tells the receiver when the end-of-file has occurred so JMODEM is able to preserve exact file-length.

®FC¯The JMODEM block.
®FL¯
®NB¯
The JMODEM block looks like this:

|< --------- First byte sent / received
20 00 01 01 .. .. .. .. .. AE 01
| | | | | | |___ CRC (high byte)
| | | | | |______ CRC (low byte)
| | | | |_______________ data bytes
| | | |________________________ type of block
| | |___________________________ block number
| |______________________________ block length (high byte)
|_________________________________ block length (low byte)
®BB¯

The Block length:

The block length is a WORD (16 bits). This allows the blocks to be 65,535 bytes long although in practice the length is not allowed to exceed 8192 bytes (plus overhead). The block-length is the length of the entire JMODEM block, not just the data-bytes.

The Block number:

The block number is a BYTE. It starts at 1 and becomes zero again after block 255. It is used to make certain that all receiption errors are detected.

The Block type:
®NB¯
This BYTE is bit-mapped to tell the receiver what kind of block has been sent. Presently there are three kinds of blocks:

00000000B Hex 00 ( Normal data )
00000001B Hex 01 ( Compressed data )
00000010B Hex 02 ( End of file )
®BB¯
The CRC:

The CRC is a WORD (16 bits). It is not a "standard" type of CRC because, unless done with hardware, a standard 16-bit polynomial would take several seconds to calculate for a long block. Instead it uses a rapid rotate and sum algorithm that is probably just as effective as the more "standard" polynomials.
®NB¯
The CRC is generated using this polynomial:

X = X + X^(2(n-mod 7))....... Where n = t(n-1)
And t = string length
®BB¯
It has the advantage of simplicity in assembly-language programming and will detect errors with a probability of about one undetected error in 2^132 (which is a very large number). It does not correct errors so its not important to use some "standard" function to generate the CRC.

The C code shows how easy it is to create and check this kind of CRC.
®PG¯
®FC¯The JMODEM Communications
Hardware Control
®FL¯
When JMODEM is first loaded for execution it checks the state of the modem-control leads. If there is no modem carrier detected, it assumes that you have connected two PCs together without a modem and will not bother to check for a dropped carrier during execution.

Since JMODEM must exercise flow-control so it can be used with high-speed modems with fixed baud rates, it also as~sumes that at the time at which it is first executed, the modem will be requesting data because there will have been very little I/O over the previous few seconds. JMODEM stores the state of RTS/CTS and DTR/DSR and uses this as a refer~ence. When transmitting data, should JMODEM find that the state of these modem-control leads has changed, it waits until the modem-control leads have reverted back to the initial state before sending any more data. This allows ANY modem to exercise flow-control with JMODEM, even those that use "pin 4" instead of "pin 20". When JMODEM is waiting, it checks to verify that the modem carrier has not been drop~ped. If the carrier is dropped, or if the user aborts, JMODEM will exit, setting a DOS ERRORLEVEL code.

You can abort JMODEM at any time by hitting Ctrl-Break or Ctrl-C. It will take several seconds for JMODEM to abort because it does not continually check these keys. Unlike previous versions, JMODEM erases the files from aborted downloads. Also, JMODEM will abort if it is unable to rename a file in the following example.

Suppose you wish to download a file called VIRUS.EXE. Sup~pose also that VIRUS.EXE already exists. Instead of over~writing your previous version of VIRUS.EXE, JMODEM has al~ways been nice and renamed it to VIRUS.OLD before creating a new file. With previous versions of JMODEM, if VIRUS.OLD already existed, JMODEM would have deleted it before renam~ing the present file to ".OLD". This no longer is done. JMODEM never deletes ANYTHING anymore except it's own abort~ed download. This should reduce the number of threats I have received!

®PG¯
®FC¯The C programmer's
Guide to JMODEM
®FL¯
Included within this package should be the following files:
JMODEM This is a Microsoft MAKE file for JMODEM.EXE.
JMODEMTC Borland's Turbo C MAKE file for JMODEM.EXE.
JMODEM EXE The executable file
JMODEMTC RSP Link response file for Borland's Turbo C
JMODEM_A C Contains the _main() routine entry point.
JMODEM_B C Parses input strings.
JMODEM_C C All of the file I/O is in this file.
JMODEM_D C Data compression/expansion, CRC calculation
JMODEM_E C Communications I/O interrupt service, etc.
JMODEM_F C Screen I/O (windows, etc)
JMODEM_G ASM Interrupt service routines (after V2.00)
JMODEM H Contains JMODEM globals and data structures.
SCREEN H Screen definitions, prototypes, structures
UART H Definitions for the 8250 UART
TEST C This tests compression /expansion, disk I/O.
TEST This is the Microsoft MAKE file for TEST.EXE
TESTTC Borland's Turbo C MAKE file for TEST.EXE
SHOW C Source for verifying execution in a DOS shell
SHOW Microsoft MAKE file for SHOW.EXE
SHOWTC Borland's Turbo C MAKE file for SHOW.EXE
SHOW EXE Executes JMODEM from a DOS shell.
TEST C Tests JMODEM data-compression and file I/O.
TEST Microsoft MAKE file for TEST.EXE
TESTTC Borland's Turbo C MAKE file for TEST.EXE
TEST EXE Executable to test file I/O and compression

If you have MicroSoft 'C' version 5.0 or later, and if your environment and paths are properly set up, you should be able to type:

MAKE JMODEM
... and a brand new version of JMODEM will be created.

If you use Borland's Turbo C, you can use the "TC" make files to do the same.

Brad Smith from Jacksonville North Carolina created the MAKE files for Turbo C and modified the source-code to accom~mo~date the different libraries used in Turbo C. His revisions will be present in all subsequent versions of JMODEM to assure compatibility with Borland's Turbo C.

Brad is a Turbo C guru and runs a BBS system in Jacksonville.
®NB¯
Brad Smith
141 Riggs Street
Jacksonville, North Carolina 28540
BBS (919) 455-5972 12/24/9600+ 24 hrs
®BB¯
With this release, there seems to be a Null-Pointer assignment error when using Borland's Small Model in TCC Version 1.5. This is a compiler bug, or more specifically a bug in the C0.ASM code provided with the compiler that you can fix.

If you are a Turbo C programmer, don't use the small model when creating JMODEM.EXE unless you repair the C0.ASM file and create a new C0S.OBJ file using the MAKE-C0.BAT file that is provided with the compiler.

To fix the null-pointer problem in Turbo-C find the following code-fragment in \LIB\C0.ASM provided with your compiler:

IFNDEF __HUGE__

; Reset un-initialized datas

xor ax, ax
mov es, cs:DGROUP@@
mov di, offset DGROUP: bdata@
mov cx, offset DGROUP: edata@
sub cx, di
rep stosb
ENDIF

Add the following code:

push ds
mov ax,DGROUP
mov ds,ax
mov word ptr ds:[0],0
pop ds


Now find this next code-fragment:

xor ax, ax
mov si, ax
mov cx, lgth_CopyRight
cld
ComputeChecksum label near
add al, [si]
adc ah, 0
inc si
loop ComputeChecksum
sub ax, CheckSum
jz ExitToDOS
mov cx, lgth_NullCheck
mov dx, offset DGROUP: NullCheck
call ErrorDisplay

Modify the code so it looks like this:

; xor ax, ax
; mov si, ax
; mov cx, lgth_CopyRight
; cld
;ComputeChecksum label near
; add al, [si]
; adc ah, 0
; inc si
; loop ComputeChecksum
; sub ax, CheckSum

push ds
mov ax,DGROUP
mov ds,ax
cmp word ptr ds:[0],0
pop ds

jz ExitToDOS
mov cx, lgth_NullCheck
mov dx, offset DGROUP: NullCheck
call ErrorDisplay


After to have done this, execute MAKE-C0.BAT for the small model library from the DOS prompt:

F:\TURBOC\LIB> MAKE-C0 SMALL

This will create a new small-model startup object file.

Just as in the MASM language files, the source code is strong~ly-typed. All function prototypes are declared and no defaults are used. You can compile at warning-level 4, the most stringent level available with Microsoft compilers, and you will get no warning errors at all. The default warning level with Borland's compiler is even more stringent. You will get a single warning error when compiling TEST.C as the compiler discovers that dummy parameter "one" in the dummy screen routine isn't used at all. It has been my experience that if you get any warnings (in real code), they MUST be fixed or they will bite you later on.

Example:
*memory++ = foo;
... will bump the memory pointer after you put foo
into memory. Suppose you get to the end of the block
and wish to index backwards.

Do you use ...
--*memory = foo;
...?

You do NOT!! You must use:

*(--memory) = foo;

Little things like this (this is a BIG, BIG bug), could cause code to work and keep you awake nights. JMODEM has been carefully written to prevent bugs like this. It is impossible to be sure that there are no bugs in even simple code so be careful if you modify the source.

You may modify JMODEM for your own use, but P L E A S E do NOT distribute the modified version on BBS systems because I do not wish to support 222,500 versions of JMODEM! If you find a bug, or wish to improve or add something that will increase the value of JMODEM without making it incompatible with previous versions, please upload your improvements to my BBS system and I may include the revisions (with your name attached) in an upcoming version. Note that there are 6 "type" bits available in the JMODEM control-byte that could be used to tell the receiver that another file is coming, etc., (for batch). Things like this could be added without destroying compatibility with previous versions.

MicroSoft C seems to have several bugs one of which affects files that are very long (over 256k). My first attempts to use C files under MicroSoft for JMODEM used the stream-I/O (FILE *) type of files. This resulted in corruption of long files. Therefore I implemented the UNIX/DOS type of file-I/O that uses handles rather than file-control blocks. These work rather well.

Starting with Version V3.06, The JMODEM distribution file will no longer contain the old JMODEM.ASM source. This is to reduce the download time. The C version is now mature enough so that there is little or no difference between the per~formance of JMODEM.COM, the assembly version, and JMODEM.EXE, the C version. The original C version was about 25 k in length. It is now only about 14.

Floating point:

Originally no floating-point libraries were used. The de~fault is still not to use any because they result in doubl~ing the size of the code. Some persons have complained that the speed (cps) indication is not very accurate. This is true because of the granularity of the time returned from DOS (one second). If you add /DFTIME to the command-line used to compile JMODEM_A.C in the "MAKE" file, the compiler will use floating-point routines for the speed calculation. The resulting JMODEM.EXE will be about 35k in length, though, so this is a trade-off. If you wish accurate timing, you pay for it in much-increased code-size.

Modems:

When JMODEM gets control, it turns ON CTS and DSR just in case the BBS program has turned them off (WILDCAT does). Some modems "hiccup" when this occurs, and the RTS line will bounce. This caused JMODEM to "wait forever" for a RTS that never occurs. Therefore I added a 1/2 second delay between the time that I first set these bits and the time I start checking for RTS and RLSD for flow-control and a possible abort. This fixed this problem. The flow-control problem is complex because user's might wish to transfer files between two computers using only three wires. In such a case, there is no flow-control and there is no modem carrier. To accom~modate a universal solution to various hookups, JMODEM checks for the state of DSR/CTS and RLSD when it first gets control. If there is no carrier at this time, JMODEM will not check for an aborted carrier during transmission or reception. If JMODEM detects a CHANGE in either DSR or CTS, it assumes this is flow-control and waits for these bits to change back to whatever they were when JMODEM first obtained control. This protocol has been used successfully since the very first version of JMODEM. There is, however, a pos~sibility of JMODEM wrongly interpreting what it finds if there is "bounce" when it first gets control. That's the reason for the delay. In any event, the normal "timeout" trap will prevent a hung system.

BBS systems:

JMODEM still gets blamed for crashing some BBS systems even though it is not JMODEM's fault. A common problem occurs with systems that use compiled BASIC. Some BBS system pro~grams assume certain characteristics about external proto~cols and will blow up when the assumption is wrong. If you use BASIC code that works like this:

PROTOSEND$ = "JMODEM S1 "
COMSTRING$ = PROTOSEND$+FILENAME$

SHELL COMSTRING$

... Then JMODEM (and other protocols) will work okay.

However, If you attempt to BLOAD, CALL, or CHAIN to it, the results will be indeterminate. This is because JMODEM allocates memory from C runtime routines that get their memory from DOS (not BASIC). BASIC will not "know" that its memory has been used by the external protocol. If you exe~cute the "SHELL" command, then you force BASIC to give up all the memory that it can afford to spare. This free memory is recorded by DOS and can be used for the external proto~col.

BBS systems written is C should execute external protocols something like this:

strcpy(command_line,"JMODEM S1 FILENAME");
system (command_line);

The C "system" command executes DOS commands from within C programs by freeing memory and then executing COMMAND.COM. Some C compilers don't have to load an aditional copy of COMMAND.COM. They use an undocumented "back-door" to the existing command interpreter! This saves memory.

This is a sneak preview of the undocumented procedure:

MOV WORD PTR [SP_SAV],SP ; Put the SP in a safe place
MOV WORD PTR [SS_SAV],SS ; Save segment registers.
MOV WORD PTR [DS_SAV],DS
MOV WORD PTR [ES_SAV],ES
MOV AX,4A00H ; Free memory
MOV BX,OFFSET TOP ; Point to the top of code
MOV CL,4 ; Bits to shift
SHR BX,CL ; Div / 16
INC BX ; Round up
INT 21H ; Free some memory
;
MOV SI,OFFSET COMMAND ; Point to the command
INT 2EH ; Make the undocumented call
CLI ; No interrupts, cleaning up
MOV DS,WORD PTR CS:[DS_SAV] ; Restore all segments
MOV ES,WORD PTR [DS_SAV]
MOV SS,WORD PTR [SS_SAV]
MOV SP,WORD PTR [SP_SAV] ; Restore stack pointer
STI ; Allow interrupts

If JMODEM and other external protocols are executed from BBS software in this manner, then you will have no problems. JMODEM preserves the BBS system communications environment so BBS systems don't have to reinitialize anything when they get control. JMODEM does not even touch the baud rate! Its not necessary to alter any communications parameters so it doesn't.

A small program, SHOW.C is provided with this distribution. It is a C program that allocates a lot of memory, writes to the memory, then executes JMODEM.EXE using the "system" command. After JMODEM returns from the shell, SHOW then continues to write to memory before exiting. Since this procedure is properly written, no system crash will occur. You can load multiple copies of COMMAND.COM to "eat" memory. Eventually there will be too little memory available for JMODEM to execute. The system will still not crash.

Help:

JMODEM is now over three years old. I first wrote it in assembly and slowly it caught on. I spent last Christmas writing it in C. Since the C release, I have received over 500 comments from persons telling me how to make it better. Most of these comments were from so-called professional programmers who complained about various things. Others complained about the comments I made about them in this document .

Please remember that an enhancement is not a "preference". If you prefer to do something one way or another then feel free to modify the code for your own use. If you find a better way to do something then please let me know.

®PG¯
®FC¯JMODEM revision history
®FL¯
The revision history has been moved to JMODEM_A.C and to JMODEM.H (identical copies). This makes it easier to keep the documentation current.

Version V3.09 adds support for absolute port addresses and IRQ numbers. This allows one to use multiple boards that use strange ports and interrupt levels. This also allows one to thoroughly screw up his system by writing to the wrong ports by accident. JMODEM now accepts:

JMODEM R(3F8:4) filename.typ

... for an input string as well as the generic port number. In this case, "3F8" is the hexadecimal port address and "4" is the IRQ number. The delimiters are required.

Version V3.08 does not do anything except make the code comply with Microsoft's interpretation of the ANSI standard so it will compile at their new "warning-level /W4" without any warning errors. Jeff Jevnisek warned me about the new C600 compiler and I had to go out and buy it. He also mod~ified the code to be "Microsoft compliant" so, as usual, there are no warning errors when compiling.

Microsoft, supplying over 80 percent of the 'C' compilers in use for the PC environment, is a force that must be accom~modated even though they are < W R O N G >, damned wrong! Here's an example of what they now REQUIRE to pass their "warning-level 4" test:

Given this CORRECT code....

short function (param)
short param;
{
return param;
}

... we now need this:

short function (short param)
{
return param;
}

ANSI allowed (read ALLOWED) the inclusion of the object size (type) within the parameter list to facilitate making the parser for the compiler. With the "old-style" method, the size of the object was not known until the next line was read so the compiler had to store the previous variable names (such a pity) until it got to the line that represent~ed the size and type of the object. Microsoft was one of the ANSI committee representatives that insisted upon the allow~ance for including this information within the parameter list. It was ALLOWED by the committee. Now any~thing not in conformance with Microsoft's WISH is flagged as an error!

The second problem is that the NULL object (not anything having to do with ANSI) was previously a generic VALUE of zero that could be assigned to any size object including pointers of all types, ASCII string terminators, etc. This is no longer the case. One must cast it to the appropriate type before use!! I got rid of all references to NULL because it no longer has the required special character~istics.

- finis -


  3 Responses to “Category : Communication (modem) tools and utilities
Archive   : JMODM311.ZIP
Filename : JMODEM_C.XYW

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/