DLOAD.C

/*  DLOAD                  16 Jan 88           Burt Mitchell               */
/*                                                                         */
/*  Host software for an PC compatible to send files to a                  */
/*  Color Computer using the DLOAD command.                                */
/*  The Coco must be running Extended Color Basic v1.1 or OLDER            */

/*  This program uses 1200 baud as it is the default for the Coco.  It is  */
/*  configured to use the PC's com1: port. To change this you will have to */
/*  edit the procedures transmit_char() and receive_char().                */

/*  This program has not been tested in the DLOADM mode as I have no way   */
/*  of getting a Coco machine language routine into the PC in the first    */
/*  place.                                                                 */

/*  To operate DLOAD:                                                      */
/*  on the PC enter     DLOAD filename.ext a                               */
/*  the PC will inform you that it is waiting.                             */
/*  on the Coco enter   DLOAD                                              */

/* Modified for use with unix by Bryan Clingman (bac@realtimeweb.com)	   */
/* 3-Jun-1997															   */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define	true	1
#define	false	0
#define	ok		1
#define	bad		0

/* literals for the DLOAD protocol */

#define	file_req	0x8A
#define	block_req	0x97
#define	NAK			0xDE
#define	ACK			0xC8
#define	EOT			0xBC
#define	ABORT		0xBC
#define	ASCII		0xFF
#define	BINARY		0x00
#define	BASIC		0x00
#define	ML			0x02
#define	block_size	127

unsigned char	chksum,
				file_type,
				asc_flag,
				proceed;
unsigned char		rx_char;
char			*tx_name;
char			*port;
FILE			*infile;
FILE			*fp;
int			tx_delay;

void transmit_char(unsigned char tx_char)
{
	fputc(tx_char, fp);
#ifdef DEBUG
	fprintf(stderr, " [%02X]", tx_char);
#endif
	usleep(tx_delay);
}

void receive_char()
{
	rx_char = fgetc(fp);
#ifdef DEBUG
	if (rx_char != 0xFF && rx_char != 0)
		fprintf(stderr, " %02X", rx_char);
#endif
	if (rx_char == ABORT)
	{
#ifdef DEBUG
		fprintf(stderr, "\n");
#endif
		fprintf(stderr, "transfer aborted by target.\n");
		exit(1);
	}
}

void initiate_transfer()
{
	chksum = (file_type ^ asc_flag);
	transmit_char(ACK);
	transmit_char(file_type);
	transmit_char(asc_flag);
	transmit_char(chksum);
}

char rcv_file_name(char *filename)
{
	int	count;
	char    sum;
	char	status;

	filename[8] = 0;
	count = 0;
	while (count <= 7)
	{
		receive_char();
		filename[count] = rx_char;
		chksum = (chksum ^ rx_char);
		++count;
	}

	receive_char();
	sum = rx_char;

#ifdef DEBUG
	fprintf(stderr, "\n");
#endif
	fprintf(stderr, "target requested \"%s\"\n", filename);

	if (sum != chksum)
	{
#ifdef DEBUG
		fprintf(stderr, "\n");
#endif
		fprintf(stderr, "filename checksum bad.\n");
		status = bad;
		filename[0] = '\0';
	}
	else
		status = ok;
	return status;
}

void send_file()
{
	int				count,
					j;
	char			tx_flag,
					xfer_done,
					first_time,
					send_new_block;
	unsigned char	file_char[130],
					xfer_length,
					sum,
					block_num,
					old_block_num;
	long int		total_xfer;

	/**/

	first_time = true;
	total_xfer = 0;
	xfer_length = 0;
	xfer_done = false;
	tx_flag = true;

	while (tx_flag == true)
	{
		send_new_block = true;

		while (rx_char != block_req)
			receive_char();

		transmit_char(block_req);

		chksum = 0;

		/* get the MSByte of the block number */

		receive_char();
		chksum = (chksum ^ rx_char);
		block_num = (rx_char << 7);

		/* get the LSByte of the block number */

		receive_char();
		chksum = (chksum ^ rx_char);
		block_num = (rx_char | block_num);

#ifdef DEBUG
		fprintf(stderr, "\nRequested block # %i\n", block_num);
#endif
		/* should we retransmit the previous block? */

		if (first_time == false)
			if (block_num == old_block_num)
				send_new_block = false;


		/* Get the checksum for the block number being requested. */
		/* Does it match our calculation?                         */
		
		receive_char();
		sum = rx_char;

		if (sum == chksum)
		{
			transmit_char(ACK);
			first_time = false;
		
			if (xfer_done == true)
			{
				/* Send a block with a length of 0 and 128 bytes of */
				/* anything along with a checksum for the block.    */
				/* This tells the Coco that the file is ended.      */
		
				tx_flag = false;
				xfer_length = 0;
		
				j = 0;
				while (j <= block_size)
				{
					file_char[j] = 0;
					++j;
				}
			}
			else
			{
				/* go ahead and read in another 128 bytes.           */
				/* If there aren't 128 bytes available pad the data  */
				/* to 128 bytes. The checksum must still be correct. */

				if (send_new_block == true)
				{
					count = 0;
					while (count <= block_size)
					{
						file_char[count] = getc(infile);
						/* The Coco can't handle linefeeds */
						if (asc_flag == ASCII)
							if (file_char[count] == '\n')
								file_char[count] = '\r';
						xfer_length = (count + 1);
						++count;
						if (feof(infile))
						{
							xfer_done = true;
							while (count <= block_size)
							{
								file_char[count] = 0;
								++count;
								if (asc_flag != ASCII)
									tx_flag = false;
							}
						}
					}
				}
				else
				{
#ifdef DEBUG
					fprintf(stderr, "\n");
#endif
					fprintf(stderr, "Re-transmitting block #%d\n", block_num);
				}
			}

			/* transmit whatever is in the buffer */

			transmit_char(xfer_length);

			chksum = 0;
			chksum = (chksum ^ xfer_length);
			count = 0;
			while (count <= block_size)
			{
				transmit_char(file_char[count]);
				chksum = (chksum ^ file_char[count]);
				++count;
			}
			transmit_char(chksum); 
		
			total_xfer = (total_xfer + xfer_length);
#ifdef DEBUG
			fprintf(stderr, "\n");
#endif
			fprintf(stderr, "Total transmitted = %ld\r", total_xfer);
#ifdef DEBUG
			fprintf(stderr, "\n");
#endif
			old_block_num = block_num;
		}
		else
		{
			fprintf(stderr, "checksum mismatch\n");
			transmit_char(NAK);
		}
	}
	fprintf(stderr, "\n");
}

void xfer_abort()
{
	transmit_char(NAK);
#ifdef DEBUG
	fprintf(stderr, "\n");
#endif
	fprintf(stderr, "transfer aborted by host\n");
	exit(1);
}

void init_port()
{
	fp = fopen(port,"a+");
	if (!fp)
		fprintf(stderr, "Error opening port\n");
	setvbuf(fp, NULL, _IONBF, 0);
}

int main(int argc, char *argv[])
{
	char    filename[9];
	char    status;

	if (argc < 4)
	{
		fprintf(stderr, "usage: DLOAD [filename.ext] [A or B] [port]\n");
		exit(1);
	}

	tx_name = argv[1];

	if ((*argv[2] == 'B') || (*argv[2] == 'b'))
	{
		file_type = ML;
		asc_flag = BINARY;
		infile = fopen(tx_name,"rb");
	}
	else
		if ((*argv[2] == 'A') || (*argv[2] == 'a'))
		{
			file_type = BASIC;
			asc_flag = ASCII;
			infile = fopen(tx_name,"r");
		}
		else
		{
			fprintf(stderr, "unknown file type\n");
			exit(1);
		}

	if (infile == NULL)
	{
		fprintf(stderr, "cant open the file to be transmitted\n");
		exit(1);
	}

	if (argc > 4)
		tx_delay = atoi(argv[4]);
	else
		tx_delay = 0;

	port = argv[3];
	init_port();

	/* wait for the coco to start the transfer */

	while (rx_char != file_req)
		receive_char();

	proceed = true;

	/* proceed with the file transfer */
	while (proceed == true)
	{
		/* get the file name from the coco. We arent using it but */
		/* it's part of the protocol. */

		transmit_char(file_req);

		status = rcv_file_name(filename);
		/* if non-empty file name, switch file */
		if (status == ok && strcmp(filename, "        "))
		{
			int lastc;

			/* zero out trailing spaces */
			for (lastc = 7; lastc > 0; lastc--)
			{
				if (filename[lastc] == ' ')
					filename[lastc] = '\0';
				else
					break;
			}
			fprintf(stderr, "trimmed to \"%s\"\n", filename);
			fclose(infile);
			/* only binary supported for now */
			infile = fopen(filename,"rb");
			if (infile == NULL)
			{
				fprintf(stderr, "cannot open %s\n", filename);
				/* abort and wait for new request */
				/* FIXME Dragon does not interpret NAK here */
				transmit_char(NAK);
				while (rx_char != file_req)
					receive_char();
				infile = fopen(tx_name, "rb");
				continue;
			}
		}

		/* tell the coco about the file it will receive. */

		initiate_transfer();

		/* now send the file */

		send_file();

		if (status == ok)
		{
			proceed = false;
		}
		else
		{
			proceed = false;
			fprintf(stderr, "file not transmitted successfully\n");
		}
	}
	return 0;
}

RTS

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies