[comp.sources.atari.st] v02i083: builds09 -- Build Motorola S-records from .ttp files

koreth@panarthea.ebay.sun.com (Steven Grimm) (10/02/89)

Submitted-by: johan@motstk.se (Johan Hagman)
Posting-number: Volume 2, Issue 83
Archive-name: builds09

These are the source files of builds 0.9, a program which creates
Motorola S-records from Atari ST binary (.ttp) files.

---
Johan Hagman           Motorola Computer Systems, Dalv. 2, 17136 Solna, Sweden
Phone: +46 8 7348800   uucp:  ..uunet!mcvax!sunic!motstk!johan
Fax:   +46 8 7354473   email: johan@motstk.{UUCP,SE}

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	builds.c
#	makefile
# This archive created: Thu Sep 28 21:49:10 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'README'" '(951 characters)'
if test -f 'README'
then
	echo shar: "will not over-write existing file 'README'"
else
sed 's/^X//' << \SHAR_EOF > 'README'
X
X		builds version 0.9  17-Sep-89
X		-----------------------------
X
XThis program was developed to allow downloading code/data to a target
X68000 system via the serial port using the Motorola S-record format.
X
XBuilds produces S2-record files from ST .ttp executables. (There are
Xthree different S-record formats; S1, S2 and S3, for 16-, 24- and 32-bit
Xaddresses, respectively.)
X
XUsage:	builds [-address] [-v] file
X
X	"address" is the (24-bit) load- and execution address, and
X	should be entered in hex format WITHOUT a leading "0x". The
X	code is	relocated in the same way as the ST does when loading
X	a program. "address" defaults to zero.
X
X	"v" displays the program version.
X
XThe S-record file is written to stdout to allow redirection to a file
Xor the serial port using your favourite shell.
X
XCompiled with Sozobon C.
X
X	Johan Hagman	Motorola Computer Systems, Stockholm, Sweden
X			e-mail:	johan@motstk.{uucp,se}
X			uucp:	..uunet!mcvax!sunic!motstk!johan
SHAR_EOF
if test 951 -ne "`wc -c < 'README'`"
then
	echo shar: "error transmitting 'README'" '(should have been 951 characters)'
fi
fi
echo shar: "extracting 'builds.c'" '(6157 characters)'
if test -f 'builds.c'
then
	echo shar: "will not over-write existing file 'builds.c'"
else
sed 's/^X//' << \SHAR_EOF > 'builds.c'
X/*
X *	@(#)builds.c	0.9	17-Sep-89
X *
X *	Builds Motorola S-records from an Atari ST object file.
X *
X *	Copyright (c) 1989 Johan Hagman.
X *
X *	This program may be freely distributed, provided it retains
X *	my copyright notice. It is provided as is, with no warranty
X *	expressed or implied.
X *
X *	History:
X *
X *	Ver   Date	Author	 Comments
X *	---  -------	------	-------------------
X *	0.9  22-Aug-88	 J.H	Initial coding.
X *	     17-Sep-89		Last edit.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X
X#define VERS	 "0.9 17-Sep-89"
X#define OBJMAGIC 0x601A		/* magic number of ST object file */
X#define	SRECL	 28		/* # of data bytes in each S-record */
X
Xtypedef unsigned char BOOLEAN;
X
Xtypedef struct {
X	WORD	magic;
X	LONG	tsiz;		/* text length */
X	LONG	dsiz;		/* data length */
X	LONG	bsiz;		/* bss length */
X	LONG	unused[3];
X	WORD	unusedToo;
X} HEADER;
X
Xstatic char 	*myName;
Xstatic LONG	relocAddr = 0L;		/* relocation address */
Xstatic HEADER	hdr;
X
X
X/*----------------------------------------
X *
X *  readHeader -- open object file, read
X *  and check header.
X */
Xstatic FILE *readHeader(fname)
Xchar *fname;
X{
X	FILE *fd;
X
X	if ((fd = fopen(fname, "rb")) == NULL) {
X		fprintf(stderr, "%s: cannot open \"%s\"\n", myName, fname);
X		exit(1);
X	}
X	if (fread(&hdr, sizeof(HEADER), 1, fd) != 1)
X		perror("fread");
X	if (hdr.magic != OBJMAGIC) {
X		fprintf(stderr, "%s: \"%s\" is not an object file\n",
X			myName, fname);
X		exit(1);
X	}
X	return(fd);
X}
X
X
X/*----------------------------------------
X *
X *  getEntry -- returns relocation offset in *val,
X *  advancing *rltpos to next entry. Returns -1L in
X *  *val at end of table.
X */
Xstatic void getEntry(fd, rltpos, val)
XFILE *fd;
XLONG *rltpos;
XLONG *val;
X{
X	static	 BOOLEAN first = TRUE;
X	register int	c;
X	LONG	 streamOffset;
X
X	if (fgetpos(fd, &streamOffset) != 0)	/* store current offset */
X	    perror("fgetpos");
X
X	if (fseek(fd, *rltpos, 0) != 0)		/* seek to relocation table */
X	    c = 0;				/* no table: PIC */
X	else
X	    do {
X		if ((c = fgetc(fd)) == EOF) {
X		    c = 0;			/* end of table */
X		    break;
X		}
X		(*rltpos)++;			/* advance to next entry */
X
X		if (first) {			/* first entry is special */
X		    first = FALSE;
X		    *val += (LONG)c << 8;
X		    c = 1;			/* loop once more */
X		} else
X		    if (c == 1)
X			*val += 0xfeL;		/* offset exceeds 0xff */
X
X	    } while (c == 1);
X	
X	if (fsetpos(fd, &streamOffset) != 0)	/* return to where we were */
X	    perror("fsetpos");	
X
X	if (c == 0)
X	    *val = -1L;				/* end of table */
X	else
X	    *val += (LONG)c;			/* accumulated rel. addr */
X}
X
X
X/*----------------------------------------
X *
X *  putSrec -- outputs a data record (S1 or S2).
X */
Xstatic void putSrec(type, addr, len, data)
Xchar type;
XLONG addr;
Xint len;
XBYTE data[];
X{
X	register BYTE	cs;			/* checksum */
X	register int	i;
X
X	/* Calculate record length */ 
X	cs = len + ((addr == -1) ? 1 : (type == '1' ? 3 : 4));
X	printf("S%c%02X", type, cs);
X
X	if (addr != -1)				/* suppress addr if -1 */
X		switch(type) {
X		case '1':				/* S1 record */
X			printf("%04lX", addr);
X			cs += (addr >> 8) + addr;
X			break;
X		case '2':				/* S2 record */
X			printf("%06lX", addr);
X			cs += (addr >> 16) + (addr >> 8) + addr;
X		/* S3 records not applicable for the 68k */
X		}
X
X	for (i = 0; i < len; i++) {
X		cs += data[i];
X		printf("%02X", data[i] & 0xff);	/* binary data */
X	}
X	printf("%02X\n", ~cs & 0xff);			/* checksum */
X}
X
X
X/*----------------------------------------
X *
X *  buildSrec -- creates the S-record file, adjusting absolute
X *  (32-bit) addresses according to user's relocation offset.
X */
Xstatic void buildSrec(fname)
Xchar *fname;
X{
X    BYTE	dlist[SRECL];
X    int		input,		/* must keep track of two input */
X		nextInput;	/*  values at each iteration */
X    LONG	rlval = 0L,
X		rltpos,		/* relocation table position in file */
X		bytesToDo,	/* # bytes in text + data section */
X		SrecAddr,
X		curOffset;	/* used for relocation */
X    register	int col;	/* "column" value for S-record data */
X    register	LONG idx;	/* index into text/data sections */
X    FILE	*fd;
X
X    fd = readHeader(fname);			/* get object file header */
X
X    /* calculate relocation table offset */
X    rltpos = sizeof(HEADER) + hdr.tsiz + hdr.dsiz + 2;
X
X    getEntry(fd, &rltpos, &rlval);		/* read relocation entry */
X
X    if (fseek(fd, (long)sizeof(HEADER), 0) != 0)	/* position at text */
X	perror("fseek");
X
X    putSrec('0', -1L, strlen(fname), fname);	/* the header record */
X
X    bytesToDo = hdr.tsiz + hdr.dsiz;
X    SrecAddr = relocAddr;
X
X    if ((input = fgetc(fd)) == EOF)		/* read first byte in file */
X	perror("fgetc");
X	
X    col = 0;
X    for (idx = curOffset = 0L; idx < bytesToDo; idx++) {
X
X	if ((nextInput = fgetc(fd)) == EOF)	/* get byte from file */
X	    perror("fgetc");
X
X	if (idx == rlval) {
X
X	    /* Oops! The next four bytes must be relocated */
X
X	    getEntry(fd, &rltpos, &rlval);	/* find next relocation entry */
X
X	    curOffset = relocAddr;		/* define relocation offset */
X	}
X
X	dlist[col] = (BYTE)(input + (curOffset >> 24));
X
X	if (curOffset != 0L)
X	    /* we're currently relocating, now check for overflow */
X	    if (nextInput + (BYTE)(curOffset >> 16) > 0xff)
X		dlist[col]++;			/* overflow */
X
X	input = nextInput;		/* advance one byte */
X	curOffset <<= 8;		/* shift in next less signif. byte */
X
X	if (++col == SRECL || idx == bytesToDo - 1) {
X
X	    /* End of line or end of data - print the record */
X
X	    putSrec('2', SrecAddr, col, dlist);
X	    col = 0;				/* begin new record */
X	    SrecAddr += SRECL;			/*   with a new address */
X	}
X    }
X    putSrec('9', -1L, 0);
X    fclose(fd);
X}
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X    char *opt;				/* arg. ptr */
X    LONG strtoul();
X
X    myName = "builds";
X
X    while (--argc > 0 && (*++argv)[0] == '-') {
X	opt = &argv[0][1];
X	switch (*opt) {
X	case 'v':
X	    printf("%s v%s\n", myName, VERS);
X	    exit(0);
X	default:
X	    if (isxdigit(*opt)) {		/* hexadecimal? */
X		relocAddr = strtoul(opt, NULL, 16);
X		break;
X	    }
X	    fprintf(stderr, "%s: illegal option \"%c\"\n", myName, *opt);
Xusage:	    fprintf(stderr, "usage: %s [-hexOffset] [-v] objFile\n", myName);
X	    exit(0);
X	}
X    }
X
X    if (argc == 0)		/* must have a filename */
X	goto usage;
X
X    buildSrec(argv[0]);
X}
SHAR_EOF
if test 6157 -ne "`wc -c < 'builds.c'`"
then
	echo shar: "error transmitting 'builds.c'" '(should have been 6157 characters)'
fi
fi
echo shar: "extracting 'makefile'" '(126 characters)'
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'makefile'
X#
X#  A makefile for builds
X#
XCCOPT	= -O
XFILES	= builds.c
XBIN	= builds.ttp
X
X$(BIN):		$(FILES)
X		cc $(CCOPT) -o $(BIN) $(FILES)
SHAR_EOF
if test 126 -ne "`wc -c < 'makefile'`"
then
	echo shar: "error transmitting 'makefile'" '(should have been 126 characters)'
fi
fi
exit 0
#	End of shell archive