home *** CD-ROM | disk | FTP | other *** search
- /*
- * ph.c
- *
- * Last Modified : November 30, 1981
- *
- * By: Larry A. Marek Aug. 10, 1980
- * Modified by: Doug Porter Nov. 30, 1981
- *
- * "PH" is a derivative of the program "Unload" by Larry Marek.
- *
- * "Unload" Copyright (c) by Larry A. Marek Not for commercial use.
- * Portions of "Ph" Copyright (c) by Doug Porter.
- * This program may not be bought or sold. For hobbiest use only!
- *
- *
- *
- * PH (Punch Hex) is intended as a partial solution to the problem
- * of how to get a file onto a CP/M system which has no telecommun-
- * ications software. It is particularly useful for getting that
- * critical first smart terminal package downline.
- *
- *
- */
-
-
-
-
-
- /*
-
-
- Transmitting a File Using PH
-
-
- To place the cart firmly before the horse, let's note that
- the receiving system must be ready to accept the file being
- transmitted before you can run PH.
-
- The command line:
-
- ph foo.bar
-
- will read the file "foo.bar" and send an Intel hex equivalent
- to the punch device. Every 10,000 characters an XOFF is
- transmitted, followed by a delay which is hopefully sufficient
- to allow PIP, running on a CP/M system which is receiving
- the hex file, to flush its buffer properly. The resulting
- ascii file can be later re-LOADed to working object code.
-
- It may be necessary to change the IOBYTE using STAT, or
- something similar, to assign the logical PUN: device to a
- serial port.
-
-
-
- Receiving a File Using PH
-
-
- Like the transmitting system, the receiving system may require
- that a serial line be assigned to one of the logical input
- devices to allow PIP to read the incoming file.
-
- After a serial line has been associated with a logical input
- device, such as RDR:, a command line such as:
-
- pip foo.hex=rdr:[b]
-
- will buffer the incoming Intel hex character stream until PIP
- detects an XOFF character or the CP/M end of file character,
- ^Z. If the character was XOFF, PIP will then flush its buffer
- to disk and return for more characters. When PIP detects
- the ^Z end of file character, it will flush its buffers and
- close the file. Then the command line
-
- load foo
-
- will create a binary file once more from the hex file. This
- file will, of course, be named foo.com. If the file is
- not a CP/M command file, simply rename it:
-
- ren foo.bar=foo.com
-
- Remember that a file in Intel hex format is about 3 times as
- large as its equivalent binary file. This means that if both
- the hex file and the final file are to be on the same disk,
- you need to have about four times as much disk space as you
- would need for the binary file alone.
-
- PH will not properly transmit a file which has non-contiguous
- random records. For CP/M command files, this matters not at
- all.
- from a serial port.
- */
-
- #include "bdscio.h"
-
- #define CLOCK_MHZ 4 /* set this for the clock speed of your system */
-
- #define DELAY 20 /* number of seconds to delay after a block */
- #define XON 17 /* ASCII Xon character */
- #define XOFF 19 /* ASCII Xoff character */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- if (argc != 2) {
- printf("\nUsage: ph file\n");
- } /* if */
-
- else {
- doit(*++argv);
- } /* else */
-
- }
-
-
- doit(file_name)
- char *file_name;
- {
- char cksum;
- int i, c, fdi, fdo;
- int charcount;
- unsigned addr;
- char infile[BUFSIZ][BUFSIZ];
-
- /*
- * take the filename given and open that
- * file for reading
- */
-
- fdi = fopen(file_name, infile);
- if (fdi == ERROR) {
- printf("can't access '%s'\n", file_name);
- exit();
- }
-
- /*
- * the main work loop
- *
- * Here the start of every line has the address and
- * other load information, then sixteen hexadecimal
- * ascii bytes. Last on the line is the checksum and
- * a carriage return, linefeed.
- */
-
- addr = 0x100; /* cp/m transients start here */
-
- charcount = 0; /* no characters sent yet */
-
- while ((c = getc(infile)) != EOF) {
-
- if (charcount >= 10000) { /* if block, */
- punchc(XOFF); /* send Xoff and delay */
- sleep(DELAY * (CLOCK_MHZ / 2) * 10);
- charcount = 0;
- }
-
- if ((addr % 16) == 0) {
- cksum = 0;
- punchc(':'); /* record mark */
- charcount++;
-
- punchc('1');
- punchc('0'); /* 16 frames to come */
- charcount += 2;
- cksum -= 0x10;
-
- /* the load address */
- punchc(tohex(addr >> 12));
- punchc(tohex(addr >> 8));
- charcount += 2;
- cksum -= (addr >> 8);
- punchc(tohex(addr >> 4));
- punchc(tohex(addr));
- charcount += 2;
- cksum -= (addr & 0xff);
-
- punchc('0'); /* record type */
- punchc('0');
- charcount += 2;
- }
-
- punchc(tohex(c >> 4));
- punchc(tohex(c));
- charcount += 2;
- cksum -= c;
-
- ++addr;
- if ((addr % 16) == 0) {
- punchc(tohex(cksum >> 4));
- punchc(tohex(cksum));
- punchc('\r');
- punchc('\n');
- charcount += 4;
- }
-
- }
-
- /*
- * The unlikely (in cp/m) case the End-o-file was
- * reached before writing a full line to the punch
- * device.
- */
-
- if ((addr % 16) != 0) {
- while ((addr % 16) != 0) {
- punchc('0');
- charcount++;
- ++addr;
- }
- punchc(tohex(cksum >> 4));
- punchc(tohex(cksum));
- punchc('\r');
- punchc('\n');
- charcount += 4;
- }
-
- /*
- * to show the end of the hex file - a zero length
- * line
- */
-
- punchc(':');
- charcount++;
- for (i = 0; i <= 1; i++) {
- punchc('0');
- charcount++;
- }
- punchc(CPMEOF); /* cp/m end of file */
- charcount++;
- }
-
- /*
- * "tohex" converts it's input to an ascii hex digit.
- * Input range is made to fit.
- */
-
- tohex(c)
- char c;
- {
- c &= 0xf; /* range 0 - F */
-
- if (c <= 9)
- c += '0';
- else
- c += ('A' - 10);
- return(c);
- }
-
-
- punchc(c) /* send c to the punch device */
- char c;
- {
- bdos(4, c);
- }