home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / BDSC / BDSC-2 / PH.CQ / PH.C
Text File  |  2000-06-30  |  6KB  |  257 lines

  1. /*
  2.  *    ph.c
  3.  *
  4.  *    Last Modified : November 30, 1981
  5.  *
  6.  *    By: Larry A. Marek        Aug. 10, 1980
  7.  *    Modified by: Doug Porter    Nov. 30, 1981
  8.  *
  9.  * "PH" is a derivative of the program "Unload" by Larry Marek.
  10.  *
  11.  * "Unload" Copyright (c) by Larry A. Marek  Not for commercial use.
  12.  * Portions of "Ph" Copyright (c) by Doug Porter.
  13.  * This program may not be bought or sold.  For hobbiest use only!
  14.  *
  15.  *
  16.  *
  17.  * PH (Punch Hex) is intended as a partial solution to the problem
  18.  * of how to get a file onto a CP/M system which has no telecommun-
  19.  * ications software.  It is particularly useful for getting that
  20.  * critical first smart terminal package downline.
  21.  * 
  22.  *
  23.  */
  24.  
  25.  
  26.  
  27.  
  28.  
  29. /*
  30.  
  31.  
  32.             Transmitting a File Using PH
  33.  
  34.  
  35.     To place the cart firmly before the horse, let's note that
  36.     the receiving system must be ready to accept the file being
  37.     transmitted before you can run PH.
  38.  
  39.     The command line:
  40.  
  41.          ph foo.bar
  42.  
  43.     will read the file "foo.bar" and send an Intel hex equivalent
  44.     to the punch device.  Every 10,000 characters an XOFF is
  45.     transmitted, followed by a delay which is hopefully sufficient
  46.     to allow PIP, running on a CP/M system which is receiving
  47.     the hex file, to flush its buffer properly.  The resulting
  48.     ascii file can be later re-LOADed to working object code.
  49.  
  50.     It may be necessary to change the IOBYTE using STAT, or
  51.     something similar, to assign the logical PUN: device to a
  52.     serial port.
  53.  
  54.  
  55.  
  56.             Receiving a File Using PH
  57.  
  58.  
  59.     Like the transmitting system, the receiving system may require
  60.     that a serial line be assigned to one of the logical input
  61.     devices to allow PIP to read the incoming file.
  62.  
  63.     After a serial line has been associated with a logical input
  64.     device, such as RDR:, a command line such as:
  65.  
  66.         pip foo.hex=rdr:[b]
  67.  
  68.     will buffer the incoming Intel hex character stream until PIP
  69.     detects an XOFF character or the CP/M end of file character,
  70.     ^Z.  If the character was XOFF, PIP will then flush its buffer
  71.     to disk and return for more characters.  When PIP detects
  72.     the ^Z end of file character, it will flush its buffers and
  73.     close the file.  Then the command line
  74.  
  75.         load foo
  76.  
  77.     will create a binary file once more from the hex file.  This
  78.     file will, of course, be named foo.com.  If the file is
  79.     not a CP/M command file, simply rename it:
  80.  
  81.         ren foo.bar=foo.com
  82.  
  83.     Remember that a file in Intel hex format is about 3 times as
  84.     large as its equivalent binary file.  This means that if both
  85.     the hex file and the final file are to be on the same disk,
  86.     you need to have about four times as much disk space as you
  87.     would need for the binary file alone.
  88.  
  89.     PH will not properly transmit a file which has non-contiguous
  90.     random records.  For CP/M command files, this matters not at
  91.     all.
  92.     from a serial port.
  93.  */
  94.  
  95. #include "bdscio.h"
  96.  
  97. #define CLOCK_MHZ 4    /* set this for the clock speed of your system */
  98.  
  99. #define DELAY    20    /* number of seconds to delay after a block */
  100. #define XON    17    /* ASCII Xon character */
  101. #define XOFF    19    /* ASCII Xoff character */
  102.  
  103. main(argc, argv)
  104. int    argc;
  105. char    **argv;
  106. {
  107.     if (argc != 2) {
  108.         printf("\nUsage: ph file\n");
  109.     } /* if */
  110.  
  111.     else {
  112.         doit(*++argv);
  113.     } /* else */
  114.  
  115. }
  116.  
  117.  
  118. doit(file_name)
  119. char *file_name;
  120. {
  121.     char    cksum;
  122.     int i, c, fdi, fdo;
  123.     int charcount;
  124.     unsigned addr;
  125.     char    infile[BUFSIZ][BUFSIZ];
  126.  
  127. /*
  128.  * take the filename given and open that
  129.  * file for reading
  130.  */
  131.  
  132.     fdi = fopen(file_name, infile);
  133.     if (fdi == ERROR) {
  134.         printf("can't access '%s'\n", file_name);
  135.         exit();
  136.     }
  137.  
  138. /*
  139.  * the main work loop
  140.  *
  141.  * Here the start of every line has the address and
  142.  * other load information, then sixteen hexadecimal
  143.  * ascii bytes.  Last on the line is the checksum and
  144.  * a carriage return, linefeed.
  145.  */
  146.  
  147.     addr = 0x100;        /* cp/m transients start here */
  148.  
  149.     charcount = 0;        /* no characters sent yet */
  150.  
  151.     while ((c = getc(infile)) != EOF) {
  152.  
  153.         if (charcount >= 10000) {    /* if block, */
  154.             punchc(XOFF);        /* send Xoff and delay */
  155.             sleep(DELAY * (CLOCK_MHZ / 2) * 10);
  156.             charcount = 0;
  157.         }
  158.  
  159.         if ((addr % 16) == 0) {
  160.             cksum = 0;
  161.             punchc(':');    /* record mark */
  162.             charcount++;
  163.  
  164.             punchc('1');
  165.             punchc('0');    /* 16 frames to come */
  166.             charcount += 2;
  167.             cksum -= 0x10;
  168.  
  169.             /* the load address */
  170.             punchc(tohex(addr >> 12));
  171.             punchc(tohex(addr >> 8));
  172.             charcount += 2;
  173.             cksum -= (addr >> 8);
  174.             punchc(tohex(addr >> 4));
  175.             punchc(tohex(addr));
  176.             charcount += 2;
  177.             cksum -= (addr & 0xff);
  178.  
  179.             punchc('0');    /* record type */
  180.             punchc('0');
  181.             charcount += 2;
  182.         }
  183.  
  184.         punchc(tohex(c >> 4));
  185.         punchc(tohex(c));
  186.         charcount += 2;
  187.         cksum -= c;
  188.  
  189.         ++addr;
  190.         if ((addr % 16) == 0) {
  191.             punchc(tohex(cksum >> 4));
  192.             punchc(tohex(cksum));
  193.             punchc('\r');
  194.             punchc('\n');
  195.             charcount += 4;
  196.         }
  197.  
  198.     }
  199.  
  200. /*
  201.  * The unlikely (in cp/m) case the End-o-file was
  202.  * reached before writing a full line to the punch
  203.  * device.
  204.  */
  205.  
  206.     if ((addr % 16) != 0) {
  207.         while ((addr % 16) != 0) {
  208.             punchc('0');
  209.             charcount++;
  210.             ++addr;
  211.         }
  212.         punchc(tohex(cksum >> 4));
  213.         punchc(tohex(cksum));
  214.         punchc('\r');
  215.         punchc('\n');
  216.         charcount += 4;
  217.     }
  218.  
  219. /*
  220.  * to show the end of the hex file -  a zero length
  221.  * line
  222.  */
  223.  
  224.     punchc(':');
  225.     charcount++;
  226.     for (i = 0; i <= 1; i++) {
  227.         punchc('0');
  228.         charcount++;
  229.     }
  230.     punchc(CPMEOF);    /* cp/m end of file */
  231.     charcount++;
  232. }
  233.  
  234. /*
  235.  * "tohex" converts it's input to an ascii hex digit.
  236.  *  Input range is made to fit.
  237.  */
  238.  
  239. tohex(c)
  240. char    c;
  241. {
  242.     c &= 0xf;        /* range 0 - F */
  243.  
  244.     if (c <= 9)
  245.         c += '0';
  246.     else
  247.         c += ('A' - 10);
  248.     return(c);
  249. }
  250.  
  251.  
  252. punchc(c)    /* send c to the punch device */
  253. char c;
  254. {
  255.     bdos(4, c);
  256. }
  257.