[net.micro.amiga] Amig* to ST conversion source

dyer@atari.UUcp (Landon Dyer) (04/08/86)

This is the source code for the Amiga to ST object code converter
that was posted a week or so ago.  Expect to do some work to make
it run on anything but a PC.

The documentation is not being re-posted here.  Contact me directly
if you need it.


-Landon			"If business is war, then I'm a prisoner of business!"
			"People are for computers."
{lll-crg!vecpyr, hoptoad}!atari!dyer



---------------- remove this line and everything above it ----------------
#
# This is a shar file.  Cut at the lines at the top and bottom and
# run the file through sh(1) to extract the source files.
#
echo x - README
sed 's/^X//' >README <<'*-*-END-of-README-*-*'
X
XThis is the source for CONVERT.EXE, intended to run under  M*DOS.
XIt has been compiled with Lattic* C version 2.something, but oth-
Xer C compilers should have no problems compiling it.
X
XAbout the source code -- well, it works.  On M*DOS.  So far.  This
Xis actually the kind of program one never wants the world to see,
X"no -- I could /never/ let the world see that I code like that!"
XWell, here it is anyway.  It was a quick hack....
X
XThe file "makefile.pc" is a makefile for a public domain  version
Xof  MAKE, which is incompatible with UN*X make(1).  If you have a
Xdifferent make, expect to have to edit the makefile.
X
XThere is byte-order dependent code  in  (at  least)  "convert.c".
XPorting to a 68000 based S*n or the ST should be easy, though.
X
XThe source for "qsort.c" has not been included.  You will need to
Xfind  your own quicksort routine, as the version I've got I can't
Xdistribute the source for.  The 4.2 BSD version work right the very
Xfirst time (impressive!)
X
X
XLandon Dyer
XAtari Corp.
*-*-END-of-README-*-*
echo x - convert.h
sed 's/^X//' >convert.h <<'*-*-END-of-convert.h-*-*'
X/* convert.h */
X
X#define	DEBUG(x)	if(debug)printf(x);
X#define	BUFFERSIZE	0x4000
X#define	OK		0
X#define	ERROR		(-1)
X
X
X/*
X * Block types.
X */
X#define	HUNKUNIT	 999
X#define	HUNKNAME	1000
X#define	HUNKCODE	1001
X#define	HUNKDATA	1002
X#define	HUNKBSS		1003
X#define	HUNKR32		1004
X#define	HUNKR16		1005
X#define	HUNKR8		1006
X#define	HUNKEXT		1007
X#define	HUNKSYMBOL	1008
X#define	HUNKDEBUG	1009
X#define	HUNKEND		1010
X#define	HUNKHEADER	1011
X#define	HUNKOVERLAY	1013
X#define	HUNKBREAK	1014
X
X
X/*
X * Hunk types.
X */
X#define	TEXT	0
X#define	DATA	1
X#define	BSS	2
X
X
X/*
X * Information about hunks:
X */
X#define	Hinfo	struct hinfo
XHinfo {
X    long hsize;		/* hunk size (bytes) */
X    long hpos;		/* position of hunk info in file (or -1L) */
X    long haddr;		/* starting address of hunk */
X    long hrsize;	/* size of relocation information (bytes) */
X    int htype;		/* hunk type (TEXT, DATA, BSS, or -1) */
X    int hunkno;		/* hunk number */
X    long *hrel;		/* -> relocation information (or NULL) */
X    Hinfo *hnext;	/* -> next hunk in order of saddr (or NULL) */
X};
*-*-END-of-convert.h-*-*
echo x - convertm.c
sed 's/^X//' >convertm.c <<'*-*-END-of-convertm.c-*-*'
X/* convertm.c */
X#include <stdio.h>
X
X/*
X * CVT - convert Amig*-format loadfiles to GEMDOS.
X *
X * THIS PROGRAM IS (C)1985 LANDON M. DYER AND MAY BE
X * DISTRIBUTED ONLY IF THE FOLLOWING CONDITIONS ARE MET:
X * 	1. YOU DO NOT MAKE A PROFIT ON IT.
X * 	2. IF YOU HAVE THE SOURCE CODE, YOU GIVE THAT AWAY, TOO.
X *	3. YOU INCLUDE THIS NOTICE IN THE SOURCE AND OBJECT CODE.
X *
X *----
X * 25-Nov-1985 lmd	Hacked it up (from earlier file-dump hacks).
X *
X */
Xchar *version = "0.50";
Xchar *date = "25-Nov-1985";
X
X#define	STRINGSIZ	256
X#define	READ		0
X#define	WRITE		1
X
Xint debug = 0;
Xint printing = 0;
X
X
X/*
X * Handle commandline
X */
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    int argno;
X    int fd, ofd;
X    char *s, ofn[STRINGSIZ], ifn[STRINGSIZ];
X
X    /*
X     * No instructions:
X     * print info about use and
X     * exit with bad return code.
X     */
X    if (argc <= 1)
X    {
X	s = "-----------------------------------------------------------------\n";
X	fprintf(stderr, s);
X	fprintf(stderr, "CVT version %s                                      %s\n", version, date);
X	fprintf(stderr, "THIS  PROGRAM IS  (C)1985  LANDON M. DYER  AND MAY BE DISTRIBUTED\n");
X	fprintf(stderr, "ONLY IF THE FOLLOWING CONDITIONS ARE MET:\n");
X	fprintf(stderr, "\t1. YOU DO NOT MAKE A PROFIT ON IT.\n");
X	fprintf(stderr, "\t2. IF YOU HAVE THE SOURCE CODE, YOU GIVE THAT AWAY, TOO.\n");
X	fprintf(stderr, "\t3. YOU INCLUDE THIS NOTICE IN THE SOURCE AND OBJECT CODE.\n");
X	fprintf(stderr, s);
X	fprintf(stderr, "Usage:\n");
X	fprintf(stderr, "CVT [-d] [-p] inputfile[.LN] [inputfile...]\n");
X	fprintf(stderr, "        ==> file.PRG output files.\n");
X	exit(1);
X    }
X
X
X    for (argno = 1; argno < argc; ++argno)
X        if (*argv[argno] == '-')
X	    for (s = &argv[argno][1]; *s; ++s)
X		switch(*s)
X		{
X		    case 'p':
X		    case 'P':
X			printing = 1;
X			printf("CVT version %s %s\n", version, date);
X			break;
X
X		    case 'd':
X		    case 'D':
X			debug = 1;
X			fprintf(stderr, "~ Debugging ON\n");
X			break;
X
X		    default:
X			fprintf(stderr, "Unknown option: %s\n", argv[argno]);
X			exit(1);
X		}
X	else {
X	    strcpy(ifn, argv[argno]);		/* file[.LN] (soft ext.) */
X	    fext(ifn, ".ln", 0);
X	    strcpy(ofn, argv[argno]);		/* file[.PRG] (hard ext.) */
X	    fext(ofn, ".prg", 1);
X
X	    fd = ebinopen(ifn, READ);
X	    ofd = ebinopen(ofn, WRITE);
X
X	    if (printing)
X		printf("%s ==> %s\n", ifn, ofn);
X
X	    convert(fd, ofd);			/* convert, then close */
X	    close(fd);
X	    close(ofd);
X	}
X}
X
X
X/*
X * Panic and give up.
X */
Xpanic(s)
Xchar *s;
X{
X    fprintf(stderr, "Panic: %s\n", s);
X    exit(1);
X}
*-*-END-of-convertm.c-*-*
echo x - convert.c
sed 's/^X//' >convert.c <<'*-*-END-of-convert.c-*-*'
X/* convert.c */
X#include <stdio.h>
X#include "convert.h"
X
Xextern int debug;	/* 1: print debugging messages */
Xextern int printing;	/* 1: print conversion statistics */
X
XHinfo *ahinfo();
X
X
X/* hunk information */
XHinfo **hunk;		/* -> vector of ptrs to Hinfo structs */
XHinfo *firsthunk;	/* -> first hunk */
Xint nhunks;		/* #hunks in input file */
Xint curhunk;		/* current hunk# */
Xint hvalid;		/* state variable (to bump curhunk) */
Xlong filpos;		/* position in input file */
Xlong siz[3];		/* segment sizes */
X
X/* relocation (fixup) information */
Xlong rsize;		/* total size of all relocation information */
Xlong *rbuf;		/* -> buffer for relocation information */
Xlong *rpos;		/* current position in relocation info buffer */
X
Xchar buf[BUFFERSIZE];	/* buffer for copying stuff */
X
X
X/*
X * Convert AMIG* binary loadfile to GEMDOS .PRG executable.
X */
Xconvert(ifd, ofd)
Xint ifd, ofd;
X{
X    /* init globals */
X    hunk = (Hinfo **)NULL;
X    firsthunk = (Hinfo *)NULL;
X    hvalid = nhunks = curhunk = 0;
X    filpos = 0L;
X    rsize = 0L;
X
X    pass1(ifd);
X    if (curhunk < nhunks)
X	panic("Bugcheck: not enough hunks in input body.");
X    bind();
X
X    if ((rbuf = (long *)malloc((int)rsize)) == NULL)
X	allerr();
X    rpos = rbuf;
X
X    output(ifd, ofd);
X    reloc(ifd, ofd);
X    release();
X}
X
X
X/*
X * Parse hunks in AMIG* binary loadfile,
X * gather information about it.
X */
Xpass1(ifd)
Xint ifd;
X{
X    long lw, junk;
X    Hinfo *h;
X
XDEBUG("~ pass1()\n");
X
X    for(;;)
X    {
X	if (readlong(ifd, &lw) == EOF)
X	    break;
X
X	switch ((int)lw)
X	{
X	    case HUNKUNIT:
X	    case HUNKNAME:
X		DEBUG("~\tHUNKUNIT or HUNKNAME\n");
X		getlong(ifd, &lw);
X		skip(ifd, lw * 4);
X		break;
X
X	    case HUNKCODE:
X		chkhunk();
X		h = hunk[curhunk];
X		getlong(ifd, &lw);		/* get size (in longs) */
X		lw *= 4;
X		h->hsize = lw;
X		h->hpos = filpos;
X		h->htype = TEXT;
X		skip(ifd, lw);
X		if (debug) dumphinfo(h);
X		break;
X
X	    case HUNKDATA:
X		chkhunk();
X		h = hunk[curhunk];
X		getlong(ifd, &lw);		/* get size (in longs) */
X		lw *= 4;
X		h->hsize = lw;
X		h->hpos = filpos;
X		h->htype = DATA;
X		skip(ifd, lw);
X		if (debug) dumphinfo(h);
X		break;
X
X	    case HUNKBSS:
X		chkhunk();
X		h = hunk[curhunk];
X		getlong(ifd, &lw);		/* get size (in longs) */
X		h->hsize = lw * 4;
X		h->htype = BSS;
X		if (debug) dumphinfo(h);
X		break;
X
X	    case HUNKR32:
X		h = hunk[curhunk];
X		for (;;)
X		{
X		    getlong(ifd, &lw);
X		    if (!lw) break;
X		    lw = (lw + 1) * 4;
X		    h->hrsize += lw + 4;
X		    skip(ifd, lw);
X		}
X		h->hrsize += 4;
X		rsize += h->hrsize + 4;
X		if(debug)printf("~\thrsize = %ld\n", h->hrsize);
X		break;
X
X	    case HUNKR16:
X		panic("16-bit relocation not supported.");
X		break;
X
X	    case HUNKR8:
X		panic("8-bit relocation not supported.");
X		break;
X
X	    case HUNKEXT:
X		panic("External symbols not supported.");
X		break;
X
X	    case HUNKSYMBOL:
X		panic("Symbols not supported.");
X		break;
X
X	    case HUNKDEBUG:
X		panic("Debug blocks not supported.");
X		break;
X
X	    case HUNKEND:
X		if (hvalid)
X		{
X		    hvalid = 0;
X		    ++curhunk;
X		}
X		if(debug)printf("~HUNKEND, curhunk = %d\n", curhunk);
X		break;
X
X	    case HUNKHEADER:
X		header(ifd);
X		break;
X
X	    case HUNKOVERLAY:
X		panic("Overlays not supported.");
X		break;
X
X	    case HUNKBREAK:
X		panic("Breaks (overlays) not supported.");
X		break;
X	}
X    }
X}
X
X
X/*
X * Sanity check about hunk adjacency (which may not be a
X * problem) and hunk number range.
X */
Xchkhunk()
X{
X    if (hvalid)
X	panic("Bugcheck: two adjacent hunks w/o HUNKEND!");
X    if (curhunk >= nhunks)
X	panic("Bugcheck: too many hunks!");
X    hvalid = 1;
X}
X
X
X/*
X * Read hunk header,
X * get info for global vars.
X *
X */
Xheader(fd)
Xint fd;
X{
X    long lw, *p;
X    long htabsize, firsthunk, lasthunk;
X    unsigned int i, j;
X
X    /*
X     * Skip library names.
X     */
X    for (;;)
X    {
X	getlong(fd, &lw);
X	if (!lw) break;
X	skip(fd, lw*4);
X    }
X
X    /* more random header info */
X    getlong(fd, &htabsize);
X    getlong(fd, &firsthunk);
X    getlong(fd, &lasthunk);
X    if (debug)
X	printf("~\thtabsize = %ld\n\tfirsthunk = %ld\n\tlasthunk = %ld\n",
X		htabsize, firsthunk, lasthunk);
X
X    /* alloc space for hunk database */
X    nhunks = (unsigned)(lasthunk - firsthunk + 1);
X    hunk = (Hinfo **)malloc(nhunks * sizeof(Hinfo));
X    if (hunk == NULL)
X	allerr();
X
X    for (j = 0; j < nhunks; ++j)
X    {
X	hunk[j] = ahinfo();
X	hunk[j]->hunkno = j;
X	getlong(fd, &hunk[j]->hsize);
X	if(debug) printf("~\t%d hsize = %ld ($%lx)\n",
X		j, hunk[j]->hsize, hunk[j]->hsize);
X    }
X}
X
X
X/*
X * Compute hunk order and starting addresses.
X */
Xbind()
X{
X    int typ, hnk;
X    long addr;
X    Hinfo *hptr;
X
XDEBUG("~ bind()\n");
X    addr = 0L;
X    hptr = firsthunk;
X    for (typ = 0; typ < 3; ++typ)
X    {
X	siz[typ] = 0L;
X	for (hnk = 0; hnk < nhunks; ++hnk)
X	    if (hunk[hnk]->htype == typ)
X	    {
X		if (firsthunk == (Hinfo *)NULL)
X		    hptr = firsthunk = hunk[hnk];
X		    else {
X			hptr->hnext = hunk[hnk];
X			hptr = hunk[hnk];
X		    }
X		siz[typ] += hptr->hsize;
X		hptr->haddr = addr;
X		addr += hptr->hsize;
X		if(debug)
X		    printf("~\thunk[%d]->haddr = $%lx\n", hnk, hptr->haddr);
X	    }
X    }
X
X    if(printing)
X	printf("text %ld ($%lx), data %ld ($%lx), bss %ld ($%lx)\n",
X		siz[0], siz[0], siz[1], siz[1], siz[2], siz[2]);
X}
X
X
X/*
X * Generate the GEMDOS output file.
X */
Xoutput(ifd, ofd)
Xint ifd, ofd;
X{
X    int i;
X    Hinfo *hu;
X
XDEBUG("~ output()\n");
X    /*
X     * Write .PRG header.
X     */
X    writeword(ofd, 0x601a);
X    for (i = 0; i < 3; i++)
X	writelong(ofd, siz[i]);
X    for (i = 0; i < 7; i++)
X	writeword(ofd, 0x0000);
X
X    for (hu = firsthunk; hu != NULL; hu = hu->hnext)
X	if (hu->htype == TEXT || hu->htype == DATA)
X	{
X	    lseek(ifd, hu->hpos, 0);
X	    randw(ifd, hu->hsize, ofd);
X
X	    if (hu->hrsize)
X	    {
X		lseek(ifd, 4L, 1);
X		*rpos++ = hu->hunkno;
X		if (read(ifd, rpos, (int)hu->hrsize) != (int)hu->hrsize)
X		    panic("Reloc info read error.");
Xif(debug)printf("~ relocsiz = %ld\n", hu->hrsize);
X		rpos += hu->hrsize >> 2;
X	    }
X	}
X}
X
X
X/*
X * Generate relocation information
X * (at the end of the output file).
X */
Xreloc(ifd, ofd)
Xint ifd, ofd;
X{
X    int cmplong();
X    long cvt2long();
X    long *rp, *drp;
X    char *crp, c;
X    int i, hno, nel;
X    long count, base, lw, addr;
XDEBUG("~ reloc()\n");
X
Xif (debug)
X  {
X    i = 0;
X    for (crp = (char *)rbuf; crp < (char *)rpos; crp += 4)
X    {
X	if (!i) printf("~ ");
X	printf("%02x%02x%02x%02x",
X	    crp[0]&0xff, crp[1]&0xff, crp[2]&0xff, crp[3]&0xff);
X	if (++i >= 8)
X	{
X	    printf("\n");
X	    i = 0;
X	} else putchar(' ');
X    }
X    putchar('\n');
X  }
X
X    /*
X     * Go back into the .PRG file and add
X     * hunk starting-offsets to the longwords
X     * that must be fixed up.
X     * 28L is the size of the GEMDOS .PRG header.
X     */
X    for (rp = rbuf; rp < rpos;)
X    {
X	hno = *rp++;
Xif(debug)printf("~	hno = %d\n", hno);
X	for (;;)
X        {
X	    *rp = cvt2long(*rp);
X	    if (!(count = *rp++)) break;
X	    *rp = cvt2long(*rp);
X	    base = hunk[(int)*rp++]->haddr;
Xif(debug)printf("~	    count = %ld, base = $%0lx\n", count, base);
X	    while (count--)
X	    {
X		*rp = cvt2long(*rp);
Xif(debug)printf("~	    seek(ifd) = %ld, seek(ofd) = %ld ",
X			hunk[hno]->hpos + *rp,
X			hunk[hno]->haddr + *rp + 28L);
X		lseek(ifd, hunk[hno]->hpos + *rp, 0);
X		lseek(ofd, hunk[hno]->haddr + *rp++ + 28L, 0);
X		readlong(ifd, &lw);
X		lw += base;
X		writelong(ofd, lw);
Xif(debug)printf("lw = $%0lx\n", lw);
X	    }
X	}
X    }
X
X
X    /*
X     * Compute and sort fixup offsets.
X     */
X    nel = 0;
X    drp = rbuf;
X    for (rp = rbuf; rp < rpos;)
X    {
X	hno = *rp++;
X	for (;;)
X	{
X	    if (!(count = *rp++)) break;
X	    ++rp;
X	    while (count--)
X	    {
X		*drp++ = hunk[hno]->haddr + *rp++;
X		++nel;
X	    }
X	}
X    }
X    rpos = drp;
X    qsort(rbuf, nel, 4, cmplong);
X
X/* print sorted info */
Xif(debug)
X  {
X    i = 0;
X    for (rp = rbuf; rp < rpos; ++rp)
X    {
X	if (!i) printf("~ ");
X	printf("%08lx", *rp);
X	if (++i >= 8)
X	{
X	    printf("\n");
X	    i = 0;
X	} else putchar(' ');
X    }
X    putchar('\n');
X  }
X
X
X    /*
X     * Write GEMDOS relocation information
X     */
X    lseek(ofd, 0L, 2);				/* to end of file */
X    rp = rbuf;
X    while (rp < rpos)
X    {
X	/* write offset to first fixup */
X	if (rp == rbuf)
X	{
X	    writelong(ofd, *rp);
X	    addr = *rp++;
Xif(debug)printf("$%lx\n", addr);
X	    continue;
X	}
X
X	if (addr >= *rp) panic("Bad relocation information.");
X	c = 254;
X	lw = *rp - addr;
X	addr = *rp++;
Xif(debug)printf("$%lx:", lw);
X	while (lw > 254)
X	{
X	    write(ofd, &c, 1);
X	    lw -= 254L;
Xif(debug)putchar('+');
X	}
X        c = (char)lw;
X	write(ofd, &c, 1);
Xif(debug)printf("$%x\n", (int)lw);
X    }
X
X    /*
X     * Terminate relocation list
X     */
X    c = 0;
X    write(ofd, &c, 1);
X}
X
X
X/*
X * Compare two longs
X * for qsort().
X */
Xcmplong(l1, l2)
Xlong *l1, *l2;
X{
X    return *l1 - *l2;
X}
X
X
X/*
X * Allocate (and initialize) a Hinfo node.
X */
XHinfo *ahinfo()
X{
X    Hinfo *h;
X
X    if (curhunk >= nhunks)
X	panic("curhunk >= nhunks, too many hunks!");
X
X    if ((h = (Hinfo *)malloc(sizeof(Hinfo))) == NULL)
X	allerr();
X    h->hsize = 0L;
X    h->hpos = 0L;
X    h->haddr = 0L;
X    h->hrsize = 0L;
X    h->htype = -1;
X    h->hrel = (long *)NULL;
X    h->hnext = (Hinfo *)NULL;
X
X    return h;
X}
X
X
X/*
X * Release memory used by hunk database.
X */
Xrelease()
X{
X    int i;
X
X    for (i = 0; i < nhunks; ++i)
X    {
X	if (hunk[i]->hrel != NULL)
X	    free(hunk[i]->hrel);
X	free(hunk[i]);
X    }
X    free(hunk);
X}
X
X
X/*
X * Skip some of the input file
X */
Xskip(fd, count)
Xint fd;
Xlong count;
X{
X    filpos += count;
X    lseek(fd, count, 1);
X}
X
X
X/*
X * Out of memory (malloc() didn't work);
X * complain and die.
X */
Xallerr()
X{
X    panic("Allocation failure, heap exhausted, I give up!\n");
X}
X
X
X/*
X * Print information about an Hinfo node.
X */
Xdumphinfo(h)
XHinfo *h;
X{
X    printf("~\thsize = %ld ($%lx), hpos = %ld, haddr = %ld ($%lx)\n",
X		h->hsize, h->hsize, h->hpos, h->haddr, h->haddr);
X    printf("~\thtype = %d ", h->htype);
X    printf("hrel = $%lx, hnext = $%lx\n",
X		(long)h->hrel, (long)h->hnext);
X}
X
X
X/*
X * Convert 68000 long to local long
X */
Xlong cvt2long(lw)
Xlong lw;
X{
X    char *out, *in;
X    long olw;
X
X    /*
X     * 8086/VAX conversion
X     */
X    in = (char *)&lw;
X    out = (char *)&olw;
X    out[0] = in[3];
X    out[1] = in[2];
X    out[2] = in[1];
X    out[3] = in[0];
X    return olw;
X}
*-*-END-of-convert.c-*-*
echo x - longio.c
sed 's/^X//' >longio.c <<'*-*-END-of-longio.c-*-*'
X#include <stdio.h>
X#include "convert.h"
X
Xextern long filpos;
Xextern int debug;
Xextern int printing;
Xextern char buf[];
X
X
X/*
X * Get a longword or complain about premature EOF
X *
X */
Xgetlong(fd, p_lw)
Xint fd;
Xlong *p_lw;
X{
X    if (readlong(fd, p_lw) == EOF)
X	panic("Premature EOF getting longword");
X    return OK;
X}
X
X
X/*
X * Read 68000 longword from file,
X * stuff it into '*p_lw' in the
X * host machine's longword format.
X *
X */
Xreadlong(fd, p_lw)
Xint fd;
Xlong *p_lw;
X{
X    char buf[4], *out;
X    int i;
X
X    out = (char *)p_lw;
X    if (read(fd, buf, 4) != 4)		/* probably end of file */
X	return EOF;
X
X    filpos += 4;
X    /*
X     * 8086/8088 conversion
X     * hh hl lh ll ==> ll lh hl hh
X     */
X    out[0] = buf[3];
X    out[1] = buf[2];
X    out[2] = buf[1];
X    out[3] = buf[0];
X}
X
X
X/*
X * Write word to file,
X * in 68000 format.
X */
Xwriteword(fd, w)
Xint fd;
Xunsigned int w;
X{
X    char buf[2], *out;
X
X    out = (char *)&w;
X    buf[0] = out[1];
X    buf[1] = out[0];
X    if (write(fd, buf, 2) != 2)
X	panic("Write error (word)");
X}
X
X
X/*
X * Write longword to file, in
X * 68000 format.
X */
Xwritelong(fd, lw)
Xint fd;
Xlong lw;
X{
X    char buf[4], *out;
X    int i;
X
X    out = (char *)&lw;
X    buf[0] = out[3];
X    buf[1] = out[2];
X    buf[2] = out[1];
X    buf[3] = out[0];
X
X    if (write(fd, buf, 4) != 4)
X	panic("Write error (longword)");
X}
X
X
X/*
X * Read-and-write (copy from one
X * file to another).
X */
Xrandw(ifd, count, ofd)
Xint ifd;
Xlong count;
Xint ofd;
X{
Xif(debug)printf("~ randw(%d, %ld, %d)\n", ifd, count, ofd);
X    for (; count > BUFFERSIZE; count -= BUFFERSIZE)
X	randw(ifd, BUFFERSIZE, ofd);
X    if (read(ifd, buf, (int)count) != (int)count)
X	panic("Read error.");
X    if (write(ofd, buf, (int)count) != (int)count)
X	panic("Write error.");
X}
X
X
X/*
X * Write single byte to file
X */
Xemit(c, fd)
Xint c;
Xint fd;
X{
X    char cc;
X
X    cc = (char)c;
X    if (write(fd, &cc, 1) != 1)
X	panic("Emit write error.");
X}
*-*-END-of-longio.c-*-*
echo x - binfio.c
sed 's/^X//' >binfio.c <<'*-*-END-of-binfio.c-*-*'
X#include <stdio.h>
X
X#define	MSDOS	1
X#define	VAXVMS	2
X#define	UNIX42	3
X#define	SYSV	4
X
X#define	READ	0
X#define	WRITE	1
X#define	MACHINE	MSDOS
X
Xebinopen(name, mode)
Xchar *name;
Xint mode;
X{
X	int fn;
X
X	if((fn = binopen(name, mode)) != -1) return fn;
X	fprintf(stderr, "Cannot %s: %s\n",
X		mode == 1 ? "create" : "open",
X		name);
X	exit(1);
X}
X
X
Xbinopen(name, mode)
Xchar *name;
Xint mode;
X{
X#if MACHINE == VAXVMS
X	if(mode == WRITE) return creat(name, 0666);
X	else return open(name, mode);
X#endif
X
X#if MACHINE == MSDOS
X#define	UNCOOKED 0x8000		/* pure binary i/o */
X	if(mode == WRITE) return creat(name, 0666 | UNCOOKED);
X	else return open(name, mode | UNCOOKED);
X#endif
X
X#if MACHINE == UNIX42
X))))) force-compiler-error
X#endif
X
X#if MACHINE == SYSV
X))))) force-compiler-error
X#endif
X}
*-*-END-of-binfio.c-*-*
echo x - efopen.c
sed 's/^X//' >efopen.c <<'*-*-END-of-efopen.c-*-*'
X#include <stdio.h>
X
X/*
X * Attempt to open a file with the given access mode.
X * Return its file descriptor, or if the open fails, print an error
X * message and exit.
X */
XFILE *efopen(name, mode)
Xchar *name, *mode;
X{
X	FILE *fp, *fopen();
X	char *msg;
X
X	if ((fp = fopen(name, mode)) != NULL)
X		return fp;
X
X	fprintf(stderr, "Cannot %s: '%s'\n",
X		strcmp(mode, "w") ? "open" : "create", name);
X	exit(1);
X}
X
X
X/*
X * Manipulate file extensions.
X * 'name' must be large enough to hold any possible filename.
X * If 'stripp' is nonzero, any old extension will be removed.  Then, if the
X * file does not already have an extension, 'extension' is appended to the
X * filename.
X */
Xchar *fext(name, extension, stripp)
Xchar *name, *extension;
Xint stripp;
X{
X	char *s, *beg;
X
X						/* go past pathname */
X	for (beg = name + strlen(name) - 1; beg > name; --beg)
X		if (stpchr("/\\", *beg))
X		{
X			++beg;
X			break;
X		}
X
X	if (stripp)				/* strip extension */
X	{
X		for (s = beg; *s && *s != '.'; ++s)
X			;
X		*s = '\0';
X	}
X
X	for (s = beg; *s != '.'; ++s)		/* add extension */
X		if (!*s)
X		{
X			strcat(beg, extension);
X			break;
X		}
X	return name;
X}
*-*-END-of-efopen.c-*-*
echo x - convert.mak
sed 's/^X//' >convert.mak <<'*-*-END-of-convert.mak-*-*'
X!----
X!
X! This is the makefile for CVT.EXE for the IBM-PC.  If you don't
X! have MAKE, then don't sweat it -- you can use the binaries or compile
X! it by hand.
X!
X! Bugs, comments, letter bombs to:
X!
X!	Landon Dyer		G.DYER@SU-SCORE.ARPA
X!	Atari Corp.		... {hoptoad, lll-crg!vecpyr}!atari!dyer
X!	1196 Borregas Ave
X!	Sunnyvale, CA 94088
X!
X!----
X!
X! No warranty is expressed or implied.  This is public domain software,
X! free for the asking.  You may modify it however you wish, but you are
X! not permitted to sell this work, or any modification of it.
X!
X!----
X!
X! You will need your OWN quicksort, as the version I use is from 4.2BSD,
X! and I'm not sure if it's legal to distribute it.
X!
X!----
X
X!
X! Change these to reflect where the libraries and so on are on your system.
X! (This is for Lattice C 2.11 or something like that).
X!
XBIN = \bin\
XCRUN = \bin\cs
XCLIB = \bin\lcs
X
XSUBRS = binfio.obj efopen.obj
XCONVERTOBJS = convertm.obj convert.obj longio.obj qsort.obj #(SUBRS)
X
Xcvt.exe : #(CONVERTOBJS)
X	link #(BIN)cs #(CONVERTOBJS),cvt,,#(BIN)lcs
X
Xconvertm.obj : convertm.c
X	lc1 convertm
X	lc2 convertm
X
Xconvert.obj : convert.c
X	lc1 convert
X	lc2 convert
X
Xqsort.obj : qsort.c
X	lc1 qsort
X	lc2 qsort
X
Xlongio.obj : longio.c
X	lc1 longio
X	lc2 longio
X
X!
X! Random tools (I port these from
X! system to system...):
X!
Xbinfio.obj : binfio.c
X	lc1 binfio
X	lc2 binfio
X
Xefopen.obj : efopen.c
X	lc1 efopen
X	lc2 efopen
X
X!
X! Copy CONVERT source to transfer disk
X!
Xtransfer :
X	copy convert.h a:
X	copy convert.c a:
X	copy convert.mak a:
X	copy convert.man a:
X	copy convert.obj a:
X	copy cvt.exe a:
X	copy convertm.c a:
X	copy convertm.obj a:
X	copy longio.c a:
X	copy longio.obj a:
X	copy binfio.c a:
X	copy binfio.obj a:
X	copy efopen.c a:
X	copy efopen.obj a:
X!	copy qsort.c a:		! I can't distribute source for this!!!
X	copy qsort.obj a:
X	copy \bin\make.bat a:
X	copy \bin\makeexe.exe a:
*-*-END-of-convert.mak-*-*
exit
---------------- remove this line and everything below it ----------------

rb@ccird2.UUCP (Rex Ballard) (04/15/86)

This is just a thank you to Landon and Atari for making some attempt
to create a "common" environment between the Atari and the Amiga.

AT LAST, someone has realised that, at some level, machines with
similar processors should be capable of running each others software.

AT LAST, a developer can create something that will can be made
available in two different markets.  Developing software for the
Atari will now make it possible to reach both the Amiga and the
Atari markets.

I will be interested in hearing from the Amiga folks how well this
object code converter works.

Thank you Landon, this may open the door to more sales of both
computers.  Keep up the good work :-) :-) :-) :-).

kim@mips.UUCP (Kim DeVaughn) (04/15/86)

[ ... go ahead, eat my bits ... ]

> This is the source code for the Amiga to ST object code converter
> that was posted a week or so ago.
> 
> The documentation is not being re-posted here.  Contact me directly
> if you need it.
> 
> -Landon

Sorry to have to do this via the net, but my mail to Landon has "bounced"
twice ...

Could you please mail the documentation to me?  For some reason, neither
it nor the binary (uuencoded ?) made it to MIPS.

Thanks in advance,
/kim

P.S.  While I'm at it, let me explain to all the netlanders who've sent me
      mail and received no reply ... if you're on ARPA (as opposed to
      USENET, I *cannot* send mail to you.  I do not know precisely why
      this is so (especially since you can send me mail), but I do know it
      *is*.
-- 

UUCP:  {decvax,ucbvax,ihnp4}!decwrl!mips!kim
DDD:   408-720-1700 x231
USPS:  MIPS Computer Systems Inc,  930 E. Arques Av,  Sunnyvale, CA 94086
CIS:   76535,25

slavenbg@prle2.UUCP (Gert Slavenburg) (04/22/86)

We where very happy to receive Landon's conversion utility from Atari binaries
to Amiga binaries, since we were dying to get as good a local development
environment on our Amiga as the Atari people allready have for quite a while !
Our experiences with the conversion of major ST packages is described below :

We received Landons package with a 3 day delay (on the 4'th of April). It
took us some time to get the uuencoded version to work, but after a day or
2 we found it sufficiently reliable for our purpose : to get TOS converted
to the Amiga. 
We used the 11/20/85 release (the Atari ROM release of TOS), and converted
it to a slightly larger objectfile on the Amiga, which took about 1 hour (!).
The first tests of TOS seemed to work reliable, though file I/O was slower
than expected. Encouraged by this succes, we proceeded on converting the
hard-disk driver (version 0.11, the most recent European release). 

At first glance the combination seemed to be working allright, however once we
started using TOS on harddisk for serious development, we found the
following unexplainable problems :

  + The system dies horribly if we visit more than some 10 nodes in our
    directory hierarchy. It complains about not enough memory, though
    we still seem to have 700 k available. We cannot do any filecopy
    (e.g. from RAMdisk to harddisk) anymore.
  + hard disk reading is VERY fast, however we have to still do all our
    compiles on a RAMdisk since writing on a more than 30 % utilised harddisk
    becomes slower than writing on a floppy.

Landon, I hope these problems with your conversion utility will be solved
soon. 
  Gert Slavenburg -:)