

		  Pete Cann's Communication Package

	  Portions Copyright (C) 1992,1993 Peter Edward Cann

	     (Please see the file README for legal junk)

This is a set of programs and data files for communication between a
PC and something external, possibly over a modem. In the case of
certain modems, fax and voice are supported.

This package is drastically different from most other communications
programs, in that it is highly modular and generally requires the
user to write batch files and/or scripts to make use of it. This is
what you might call a "hacker style" paradigm (not to be confused
with "cracker", generally an infantile individual who feels so
insignificant that they screw other people in a desperate attempt to
feel powerful). Hackers are people who are very comfortable with
computers, and like to have a lot of control and to know what's going
on.

The source code for all of these programs is included in the
distribution, so if you know C you have all the information I do now.
This C is MicroSoft QuickC, of which no endorsement should
necessarily be inferred. Some of the style is pre-ANSI. The
formatting style is that mandated by God (which is odd 'cause I'm an
Atheist). I apologize for all my lapses in rigor. It's amazing how
much better a programmer you are at the end of your first 10,000-line
project than at the beginning of it!

All of the programs give USAGE: information if invoked without
arguments. All of the programs that use a port can use COM 1 through
8, but COM 5 and 6 are only for AT and later machines and have not
been tested. Speeds are given in units of 100 bps, such as: 24, 96,
384 or 576. All speeds that it is possible to specify thus are
supported if the IBM can do them. The speed 0, although it shouldn't
be meaningful, stuffs 0x0000 into the divisor latch, in case you want
to do that.

The environment variable PCCPPATH can be used to tell some of the
programs where to find PCCP files, such as emu files and scripts.

NOTE: These programs were developed under MS-DOS 3.something, and
have been used fairly well under 5.something. If you're running any
wierd stuff on top of DOS, i.e. desktops, Windows, etc., etc., this
stuff may fail, possibly in a very nasty way. Of course, I'm not
saying it won't do that anyway! Caveat usor!

NOTE ON 16550 UARTS: I enable the FIFOs if present, with the receive
threshold at one byte, then put them back the way I found them when
done. I do NOT, however, gate 16 bytes for transmit every time the
flag comes ready. (Icky, icky, icky! Take my PC, please!) This
completely normal technique may highlight a timing bug in some
internal modem virtual UARTS. In this case, use a higher speed.

NOTE ON MS-DOS: MS-DOS, through version 5, at least, apparently
does not increment the date at midnight on the clock interrupt.
If you're not waiting for a keyboard character or something like
that at the time, it appears that your date just never
increments. I'm considering how to work around this disgusting
bit of slobitude (or is it slobosity?), but at the moment it
just happens.

NOTE ON VIRUSES: I don't think I have a virus, but you never know. If
these executables get irremediably infested, you should hopefully be
able to compile the source on a clean system, unless of course some
pathetic washout has stuck virus source into the source!

The program TERM is a terminal emulator. It takes an emulation file,
which you create or modify with EMUED. EMUED lets you specify
strings to send for any programmable key, and lets you enter strings
of characters and substitution tokens to invoke functions. These
would be the "escape sequences", although they need not begin with
Escape. The token codes are in EMU.H. The emulation facility also
provides a graphics character substitution table for graphics
character commands. TERM and EMUED look in the directory named by the
PCCPPATH environment variable for emulation files, if PCCPPATH is
set. The program CCODES types a hex listing of display character
codes for use when assigning graphics characters in EMUED.

TERM generates a CRLF in response to a Linefeed character, so it is
often desirable to program an emulation to do a DOWN in response to a
Linefeed. For LF insertion, the function CRLF can be performed in
response to a CR. If the emulation file basename is prefixed with a
plus sign (+), local echo is activated.

The program TERMPLAY will step a file through an emulation.

The program MASTERM invokes term with the three or four arguments,
but if you exit TERM you get a menu for file transfers or beginning a
dribble file. The file transfer programs are four variations on
XMODEM in each direction, and have fairly clear names. Also, you can
use mind-boggling port speeds without a 550, 'cause I only go out to
disk between packets.

If you want ZMODEM, *you* can write the thing, as soon as you come to
after reading the spec! I *have* added my very own XMODEM CRC 16K
protocol, which took me very nearly an entire half hour! It ought to
do better than 95% at V.32bis/V.42 sending a zip.  This is straight
XMODEM CRC with a HI6 (0xb6, i.e. 0x80+'6') packet intro and double
tail-end fallback. It's 16K so people won't burn me in effigy when
28.8 kbps arrives, which is about all she wrote for your basic POTS
line. When ISDN happens, hopefully there will be a sensible standard.

There are a lot of fairly sick interpretations of "automatic" XMODEM
these days. One important trick is to nail your send in there *fast*,
before the receiver stops offerring to do CRC. If you see a squiggle
instead of a C it's too late; they want to do checksum (bleah!).

The program SESSION is a simple host program, for use AFTER password
validation by the script facility. It is hard-coded for 8n1 bits. It
expects the modem to be in AT&C1 mode, that is, Carrier Detect
conveys information. The last (optional) two arguments to SESSION are
directories for download and upload. If they are given, they are
prepended to the entered pathname in file transfer operations. If a
directory is given, dot-dot (..) is prohibited in pathnames and the
Shell option is not available. Session uses PCCPPATH to find
executables, to speed up loading.

The environment of any subschell contains REMOTE=YES, so you can do

	IF NOT "%REMOTE%"=="YES" THING

in a batch file, where THING is something that would be bad to do
from a comport, such as run a display editor. SESSION terminates if
Carrier Detect goes false, unless it is running the shell.

The program MESSIN accepts a message from the port and appends it to
the specified file. This is for email to the sysop. The program
MESSOUT asks for a filename in or below the specified directory and
displays it with pagination. Security is achieved through sparse
naming.

The program COMSCRPT runs scripts. It is very powerful, with multiple
branching look-fors, timeouts and retry limits. The program SCRCHK
checks scripts for parsability and undefined label references. The
USAGE: message for SCRCHK also tells you the script buffer capacity
for both of these, which is a #define.

The script file must have the extension ".SCR". If the PCCPPATH
environment variable is set, the program looks for the script there.
The program loads the script into RAM and then executes it. Lines are
limited to 80 characters.

String fields in a script start immediately after the delimiting
space, even if that means they start with whitespace. Trailing
whitespace is also included in a string field. If your editor gives
you no way to tell if you have trailing whitespace, why are you using
it? I'm quite partial to any good EMACS. (This should not be taken as
an unqualified endorsement of RMS. Abolishing intellectual property
altogether strikes me as being similar to communism, in that it's a
nice idea and it might be workable in a few hundred years.)

At parse time, a $1 through $9 will be replaced with the
corresponding argument to COMSCRPT starting after the name of the
script. $@ expands to the value of PCCPPATH followed by \ if PCCPPATH
is set; otherwise it expands (to use the term loosely) into nothing,
i.e. the $@ is simply diked out. $<digit> on the other hand will bomb
if the arg is not supplied. $ is an escape; to use it without
expansion, use two of them and you'll end up with one. $ is expanded
pretty much before any other parsing.

The first line in a script file must be <port#> <speed> <db><par><sb>
followed optionally by zero to turn off flow control. $<digit> is
permitted.

The characters '|' and '~' are special. '|' means CR in <, > and k
lines; and newline in !  lines. '~' means 0.4 second delay in < lines
and bell in ! lines.  (In > lines it means itself.) Also, in <, >, !
and k lines, `xx (backquote followed by two hex digits) expands to
the specified character code. Letters in the hex number may be either
case.  There is no validity checking. `00 will terminate a > line.
Also in < lines, ^ means break. To send a magic character, use its
hex code with a backquote.

The first line of the script file is the first three arguments as for
TERM, space-delimited. In subsequent lines, the first character of
each line is the command; the rest of the line (after the delimiting
space) is argument(s). A final string argument may include spaces,
and begins after the delimiting space. Blank lines are ignored.

The command characters are as follows:

;
	{introduces comment; line ignored; space not required}

: <decimal number 0-255>
	{label for conditional or unconditional goto} 

g <label #>
	{goto label #}

= <speed>
= <comnum> <speed> <databits><parity><stopbits> <flow ctl flag>
	{Set new port speed in hundreds of bps. Zero sets DL=0}
	{Long form simply closes old port and tries to open new one}
	{Waits for shift register to empty; leaves handshake alone}

* <label #>
	{establishes a demon to goto label upon Control-X from keyboard}
	{* -1 cancels}

r <label #> <retries> <register>
	{increments specified retry register}
	{<retries> is an int, try 32766 for a dummy to just increment}
	{zeros register and goes to label if register > retries}
	{register is 0 - 255}

0 <retry register>
	{zeros the specified retry register}

" <retry register>
	{prints contents of retry register to local screen}

p <seconds>
p <seconds> <processing>
p t<ticks>
p t<ticks> <processing>
	{processes pending look-fors (>); falls through upon timeout}
	{clears pending look-for list upon completion}
	{zero seconds indicates no timeout}
	{ticks are 1/18.2 second (IBM PC)}
	{scanned characters are displayed and maybe sent to file}
	{processing: 0 = none, 1 = visible line buffer, 2 = password buffer}

> <label #> <string>
	{look for string upon p command; if hit goto label}
	{incoming linefeeds ignored}
	{first come, first served}
	{maximum of 32 active > demons allowed}

f
	{flush characters previously received from port}
	{does NOT append characters to file}

o <label #> <string>
	{open file <string> for append of scanned characters & ! messages}
	{or close current file if string is "*"}
	{goto label if error}

i <label #> <string>
	{open file <string> for input}
	{or close current file if string is "*"}
	{goto label if error}

t <label #>
	{transfer one line of input file out the port}
	{newline characters are not sent}
	{goto label if EOF}

? <label #>
	{goto label if Tx Hold Reg Empty is false,}
	{or in CTS flow control mode & CTS is false}

d <label #>
	{goto label if Carrier Detect is true}

< <string>
	{send string to port}

! <string>
	{send string to console}

x <command line string>
	{run executable file with arguments and wait for termination}

# <label #> <return value>
	{jump to label if most recent "x" command returned <= <return value>}

s <label #> <command line string>
	{run system command line and wait for termination}
	{goto label # if error in running command.com}
	{will not report errors within command string}

+
	{Raise DTR handshake line}

-
	{Drop DTR handshake line}

k <label> <character>
	{set branch to label upon keyboard character received in w or m}
	(this is a scanf(), so space must be `20 and tab `09}
	{limit 64 simultaneous character scans pending}

w <seconds>
	{wait seconds for keyboard character, performing k dispatching}
	{fall through if no character in <seconds> seconds}
	{zero seconds indicates no timeout}
	{clears all k commands pending upon any termination}

m <seconds>
m t<ticks>
	{mnemonic: monitor -- combines functions of 'p' and 'w';}
	{except that no front end services are provided.}
	{ticks are 1/18.2 second (IBM PC)}
	{clears both kinds of scans when it exits}

c
	{clears pending lookfors and keys (> and k)}

l <label #> <jump register #>
	{load label into jump register. -1 unloads register}
	{jump registers are 0 - 255}

j <jump register #>
	{jump to label previously loaded into jump register}
	{falls through if register is unloaded}

q <exit code>
	{quit with exit code}
	{codes other than zero under 128 are reserved to internals}

SUGGESTED CONVENTION: When a body of code is to be used as a
subroutine, an elegant convention is to jump via the jump register
having the same index as the routine entry label upon completion.

When scripting modem commands, which is how you're intended to
configure and dial the modem, if the modem doesn't respond, try a ~
before and after the at, for instance:

	< ~at~&f&c1&d2|

The program SCRCHK types a listing of the argument script file giving
statement numbers, which are not the same as line numbers. It leaves
out blank lines for some reason. It also detects some errors,
including potential branching to undefined labels. It prints out a
table of label numbers with their corresponding line numbers.

During execution of a script, Control-C will cancel and Control-X can
redirect the script on an interrupt basis.

All of the I/O programs except TERM pay attention to CTS. (Comscrpt
is configurable.) None of them do XON/XOFF. The computer is assumed
to be fast enough to keep up. However, since DOS video is very slow,
TERM will suspend display if an interrupt-routine buffer overrun
threatens.


FAX PROGRAMS

The fax facility is intended primarily for modems based on chips and
firmware from Rockwell International, operating in Rockwell's
conception, circa 1992, of the TIA draft Class 2 standard. This may
be relevant with regard to port speed changes required, and
especially with regard to bit order. I haven't seen the new official
Class 2 standard yet.

Nothing in this section assumes filename extentions; you must give
the complete filename.

RCVFAX receives a fax (surprize!). It is intended to be called
immediately after the "FAX" response in +FAA=1, or immediately after
answer in +FCLASS=2. See HOSTDEMO.SCR for how to configure the
faxmodem. RCVFAX uses the first speed until it sees the "+FCON"
message, then switches to the second speed, which will generally be
19200 with earlier Rockwell-based modems. It stimulates page
transmits, and stores the session in the specified directory in a
file of which the name is the universal time as an 8-digit hex number
with the extension .RFX.

Since the filenames are awkward, FAXMANIP, when run in the fax
directory, displays RFX files as dates and times, and allows you
to convert or delete. A secret FAXMANIP function is E, which will
run a system call on the second argument, space, filename. This
is intended for editing, by the adventurous. Since fax files are
wonderfully compact, they are a good way to store a document. I
suggest that, if you want to name a fax file, you make it
<name>.NRF, for Named Received Fax. Don't alter the basename and
leave it .RFX, since FAXMANIP will read the name as a garbage
date, or explode.

RFXTOPCX converts an RFX file to a series of PCX files, prompting for
the name of each page file and reporting status. This now uses a
quarter-meg state table file, STATMACH.DAT. If you don't need the
speed, delete both and rename OLDRTOP.EXE to RFXTOPCX.EXE. The old
one will do debug mode if given a second argument. The old one skips
garbage to the next EOL while the new one just croaks on garbage.
Fixing the new one would have slowed it down. Some faxmodems and/or
software may send some garbage. If you don't want to delete the new
one you can rename it FASTRTOP. Whichever you don't normally use can
be accessed using the E feature of FAXMANIP, above.

VIEWPCX displays a fax PCX file on the monitor. It has not been
tested with EGA or CGA yet, and doesn't support SVGA yet, although it
will try to configure anything it doesn't recognize as VGA 640x480x1.
Invoked without arguments it gives usage and command keys. In zoom
mode, it uses black-priority within lines and pot-luck among lines.

BJFAXPCX prints a fax PCX file to a Cannon BJ-type printer on a
parallel port, with appropriate scaling.

ASCTOSFX is a simple ASCII to Fax converter. The present font is
fixed-width because variable width fonts are a pain in the wazoo if
you're trying to line things up, and I couldn't face myself in the
morning if you couldn't fax source code. The font was generated by a
freeware version of TeX: EMTeX by Eberhard Mattes. I think the font
is public domain, but I'm in the process of inquiring. It's name is
Computer Modern Typewriter, except I added some glyphs. It's really
quite pretty. ASCTOSFX defaults to dumb; an extra argument puts it
into pretty mode, with nice margins all around. ASCTOSFX will tell
you if PCCPFROM isn't set, but that won't affect conversion. To
include a PCX file, use Control-P <pathname> <newline> on a line by
itself. The image must be one plane, one bit deep, and fit on a page.
Use -<SP><pathname> for flush left and + for flush right. The default
is centered on the page. - is for signatures, for example.

SNDFAX sends faxes prepared by the above. It tries to use the
environment variable PCCPFROM to get the originator telephone number,
as required for standalone fax machines by USA regulations (there
seems to be some consensus that fax software is responsible for this
in a faxmodem situation). The header is seven-segment, because fonts
are fat, so only digits and hyphen are allowed, to a maximum of 40
characters in the sender telephone number field. I'm sorry about
guzzling environment space, but two file finds would be too much.

Parties not subject to USA FCC regulations may set PCCPFROM to a
string of all-invalid characters, for example:

	set PCCPFROM=dummheit

I'm sorry about the inconvenience to such users, but in most cases my
government would find it a lot more convenient to ruin my life than
yours would.

SFXTORFX does what it says; it was the easiest way for me to debug
ASCTOSFX, and since I had it I threw it in the distribution.


VOICE PROGRAMS

VOICETX issues the #VTX command, waits for CONNECT and plays the
file. Optional arguments are shielded report codes upon which to
terminate; the exit code is the zero-based index of the report among
the reports armed on the command line. Normal end-of-play is 128.
Nasties are higher. Command echoes, responses and all shielded codes
are reported to the screen. If you have an internal modem with a
processor virtual UART timing bug, you might need to use 57.6 kbps
even though 38.4 ought to work.

VOICERX issues the #VRX command, waits for CONNECT and plays the
file. If the specified file ends in '\', it is taken to be a
directory and the hex utime is used with the extension .VCE, ala
RCVFAX. Reports and exit codes are the same as above, also output.

RAMREC is like VOICERX except that it records into RAM without going
out to disk, and doesn't terminate unless you run out of RAM or hit a
key on the console. It's intended for recording greetings at high
speed without a 550. It has optional arguments for using a DTMF burst
as a time reference mark, and recording with in and out times. Times
are ticks, i.e. 1/18.2 second. Error is up to -1.

VBROWSE is for playing utime messages, such as picking up your
voicemail. It uses the following voice files, located in PCCPPATH:

	 * NOFILES.VCE: "There are no files in the directory."
	 * ENTSHFB.VCE: "entries exist. How far back?"
	 * INSTRUC.VCE "Cancel any playback with star. At any prompt,
	 *	     dial digits, star to clear, pound to enter.
		     Entering nothing exits."
	 * DELETE.VCE "Dial 3 pound to delete, or just pound to proceed."
	 * DELETED.VCE "You have already deleted that message."
	 * <digit>RISE.VCE Decimal digit with rising inflection.
	 * <digit>DIP.VCE Decimal digit with dip inflection.
	 * <digit>FALL.VCE Decimal digit with falling inflection.
	 * POINT.VCE "Point" with mild dip inflection.
	 * AT.VCE "At" with mild dip inflection

To record the digits, you need to be able to trim them to get
acceptable sequence speed. If the editing source is time-quantized,
the sampling rate should preferably be, say, twice that of the
target. I suggest that you not lose the digits I provided.

My digits were originally recorded on a consumer stereo cassette
deck, with a DTMF burst about a second before the good audio, using
the editing feature of RAMREC. The arguments were derived for each
digit segment by rough timing and then iteratively tuned. The tape
recording was made through a graphic equalizer, with 125 Hz and below
at -12 dB, 250 Hz at -4 dB, 500 Hz at -2 dB, 1 kHz at 0 dB, 2 kHz at
+2 dB, 4 kHz at +4 dB, and 8 kHz and above at -12 dB.

The mic was a Radio Shack bottom-of-the-line quasi-professional
dynamic. There may be a bit of extra hiss, as the mic-line mixer I
built runs the mic right into an LM318. You don't do that for real
stuff because of the noise of the op-amp; if I wanted to blow the
extra $40 I would have used a good transformer on the mic to boost
the voltage to where the op-amp wouldn't mess it up.

The delete option in VBROWSE is suppressed unless enabled with a
command line argument. Call without arguments for USAGE. Modem and
port settings must be correct for the file or vice versa.

VCEMANIP is just like FAXMANIP except that it calls VOICETX instead
of the fax converter. You use it inside a script to hear your
messages while at the computer. The script would do #VLS=1, #VLS=2 or
some such. You have to give it the port and speed to pass to VOICETX.


SCRIPTS

SENDFAX.SCR sends a fax. Who'd a thunk it!

HOSTDEMO.SCR is an example of a simple triple host script. It doesn't
use all the features, like email and restricted file transfer. CHANGE
THE PASSWORDS before you use it, unless you want to see your
unauthorized biography in a supermarket periodical!

SPKR.SCR engages switches the modem to 2-bit local speaker operation
and runs VCEMANIP, then resets the modem. You use it (drum roll,
please) for listening to voice messages.


-----------------------------------------------------------------
RELEASE NOTES:

I've been very bad about release notes. In 053, file transfer won't
abort until the second CAN, comscrpt will recognize the first char of
a sequence even if it's the char that resets the scan for the
sequence, and I may have fixed other stuff.

In 054, I'm handling ANSI attributes differently, based on new info
from the Argus ANSI forum. I'm still not going to support remote key
reprogram though, nor alternative screen modes. Non-white colors are
now low-intensity unless bold, and faint only works for white. This
seems to be how folks are doing ANSI on PCs. Emulation now supports
ANSI CPR. Also EMUED has a better user interface.

055 adds 16550 support, I think (I don't have one). Probably not
relevant except for dribble in TERM, unless I ever get around to
doing Zmodem.

056 changes the exit chord for TERM, cause I just hit the old one by
accident myself and was annoyed. It also adds file-hacking to
COMSCRPT.

057 corrects an esthetic bug in EMUED and an error reporting bug in
SCRCHK. I also added the Jump Register feature to COMSCRPT, and made
SCRCHK not output the table if there are unlisted label errors.

058 fixes a bug in RFXTOPCX that caused it to choke if there was no
Sender ID message. It also adds a PCX file viewer and a PCX file
printer. Also, RFXTOPCX is massively redesigned, including my amazing
state machine method of fax decoding, for mondo speed increase.
STATMACH.DAT is the table now used by RFXTOPCX. It also adds the $
substitution operator to COMSCRPT. Also, PCCPPATH is not prepended to
<drive>:<path>, \<path>, or .\<path>. Also, an obsolete reference to
TERMPATH was replaced with PCCPPATH. Also, I think it was around here
that I added VIEWPCX. Also, COMSCRPT now does arguments. Also I took
the label out of X in COMSCRPT and added the # command.

I think it's time for a new revision! 059 changes bit rate
specifications to units of 100 bps, and allows any possible such
speed. (You can now do 115200).

Barf! Bletch! I wasn't using an absolute path for the first TERM
within MASTERM. All better in 060. PORT.C has a lot of comments added
to teach people about IBM UART programming.

In 061, COMSCRPT now substitutes zero-character and two-character
command line arguments properly. (Boy, that was a stupid one!)

In 062, COMSCRPT is now a multi-data-and-code-segment executable,
with a separate parse-and-validate module shared with SCRCHK, which
required having a multi-data-and-code-segments version of PORT.OBJ,
which is now provided for in the MAKEFILE. Due to a disgusting SickC
problem, I'm now allocating the program buffer the hard way. Also, I
added Flow Control Control (still no XON/XOFF; that would be a pain).
Default is on, which is what you used to be stuck with.  No more
burned fingers for the wierd gizmo community! (Or at least only 3/5
as many, unless you're also using XMODEM, which requires DCD!) Also,
fixed a fall-through for COMSCRPT's C command. Also added " function;
handy for abusing things. Also made EMUED (k) a bit more coherent.

In 063, everybody waits for last character to shift out before
restoring port. ASCIIS restores port. COMSCRPT has = command. Fax
goodies are in, but still have to do federal stripe in SNDFAX, which
has some elements of such in source that are not yet used.

064 has the USA federal stripe in SNDFAX. The = command in COMSCRPT
now takes zero, same as the top line.

065 has voice record and play for Rockwell (TIA?) modems. I also
mucked around a bit with MANUAL and README. It also has the pretty
mode in ASCTOSFX. Also, I redid RCVFAX to use hand-rolled file
buffering. I was using a stream, and it worked fine, but the fact
that -1 is a bit magic was bugging the hell out of me. Also, SCRCHK
will now still tell you what labels are available even if you
duplicated a label, so now you can actually fix your booboo! Nice,
huh? Also, COMSCRPT now frees unneeded RAM; this might make a
difference to something you spawn. ("Nobody could possibly need more
than 640 k." Come on, PowerPC!!!) Also (I love that word), I added
XMODEM CRC 16K file transfers. Yet even more also, FAXMANIP no longer
trashes itself when you call an editor with a non-short name.  Also,
I made SNDFAX use XON/OFF only and ignore CTS. Also, I changed some
stuff in RCVFAX that looked doubtful. Also, OLDRTOP now skips bits
after seven zeros to get a genuine 11-zero EOL. Since some faxmodems
apparently send junk sometimes, this can be vital. RFXTOPCX is not
yet so forgiving.

066 started as a complete new compile, so I decided to give it a new
rev number. Fixed minor bug in case of initial CAN in Xmodem sends.
Made all Xmodem senders print out hex response characters from other
end, so you can tell what sick conception of Xmodem the other guy is
using. I was having trouble working with a board, compiled this into
XMCRCS.C while on line, and then it worked great. Possible code
alignment issue; I have *got* to write my own compiler! VIEWPCX was
also modified to implement horizontal black priority for better zoomed
viewing of typical faxes.

067 Yow, hacking frenzy! COMSCRPT has had the '=' command expanded,
and line buffering (optional) added to the 'p' command. The 'm'
command combines 'w' and 'p', but without line buffering. Also, only
linefeeds *without* the high bit set are now discarded in the scan
functions. (In line buffering, they turn into CR's.) The high bit is
no longer ignored in scans. VIEWPCX has a rotate 180 function on the
DELETE key; exit has been moved to the ESCape key. Sorry. Also fixed
a flaw in the priority hack. SNDFAX now ORs segments at the corners
in the federal stripe, 'cause it was real ugly the old way. Also,
ASCTOSFX now gives a nonfatal message if the PCCPFROM environment
variable is not set. Also, XMCRC16S has been fixed to revert to
128-byte blocks after reverting to 1k blocks; it was a bit confused.
Also, VIEWPCX emits a less irritating, custom beep when you thud.

068 has PCX image inclusion in ASCTOSFX. I also fixed a remarkable
bonehead move in that file, re not zeroing the index on explicit
flush. The voice stuff seems pretty good; still have to record stock
prompts, etc. Also, in the xmodem protocols, kbhit(), which has
the speed of a garden slug on a cold morning, has been replaced
by bios keyboard calls.

069 has voice prompts and various little voice tweaks. RAMREC has
editing features. Also, COMSCRPT no longer ignores Linefeed while
scanning. It seemed handy at first, but the more I thought about it,
the more evil and perverted it seemed. COMSCRPT also also lets you
optionally specify 'p' and 'm' waits in ticks. NOTE: 069 has had
somewhat poor subversion control.

070 has 3-bit prompts with better EQ. Also, COMSCRPT now expands $@
to <PCCPPATH>\. Also, I evidently did something to VBROWSE, but I
don't remember what. Also, VCEMANIP and FAXMANIP now take an optional
argument to specify the directory. This argument is mandatory in
FAXMANIP if you want to use the secret editor feature. Also, COMSCRPT
has an internal modification in dribble output to work around an
apparent MicroSoft bug.

071 has a slightly modified HOSTDEMO.SCR. It is also zipped in
PKZip204g, which is apparently all the rage these days. Of course, if
you're reading this, you don't care. 0DIP.VCE, 7DIP.VCE and 9DIP.VCE
were also re-dubbed with better trimming.

072 And off we go again! Browsing through Que's DOS book, I saw that
the authors were massively confused about the tick frequency, as
evidenced by the fact that they stated that a specific number divided
by another specific number was exactly equal to something that it was
in fact not exactly equal to. Being massively fed up with all the
rumors about tick frequency, I measured it! (No!) It's exactly
nothing, except per DOS day. Hence, there's a new include file,
TPERDAY.H, and everything now uses it. This is critical for timing
functions not going bananas across midnight. Also, the `m' command in
COMSCRPT now times out properly; I had been scanning the time
argument into a string as an int.

073: XMODEM receive variants have better error messages.
Documentation of COMSCRPT 'k' command updated. New triple host demo
scripts. RAMREC now only kicks the modem every three seconds after
the stop time, rather than every time it gets a character. FXF.H is
now included in the ZIPLIST and so you hopefully actually have it
(I'm such a slob!).

074 has everything modified to do its own tick timing with a tick
interrupt handler. The file TPERDAY.H is no longer included. It turns
out that if you call the bios tick time function and it just turned
midnight, DOS never hears about it. Naturally, MicroSoft doesn't
point that out in the documentation of _bios_timeofday() in the
QuickC manual, although they do see fit to pad the product out with
tutorials out the wazoo.

075 has a fixed-up HOSTDEMO.SCR.

076 has a fix of a serious bug introduced while fixing the calendar
bug. It was possible to do a Control-C interrupt and not have the
interrupt vectors cauterized, especially during the pre-execute
phases of COMSCRPT. Everything is hopefully quite rigorous now,
except poot() in VIEWPCX, which doesn't do typeout or disk access and
thus should be OK.
