/* $Header$ */
/*
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 */
/*
 * Download Z80 load module into the NASCOM
 *
 * Johan Stevenson, Vrije Universiteit, Amsterdam
 * Adapted (untested) to new ack.out format by
 * Ceriel Jacobs, Vrije Universiteit, Amsterdam
 */
#include	<stdio.h>
#include	<assert.h>
#include	<sgtty.h>
#include	<signal.h>
#include	<out.h>

int	check;
int	nascom = 1;
int	nl = '\037';
int	zero = 0;
int	disp = 0;

char	hex[] = "0123456789ABCDEF";

char *progname;

struct sgttyb	ttynormal;
struct sgttyb	ttyraw;
int		rawmode = 0;

struct outhead ohead;
struct outsect sect[MAXSECT];

stop(code) {
	if (rawmode)
		stty(1, &ttynormal);
	exit(code);
}

main(argc,argv) char **argv; {
	register unsigned nd;
	long pc;
	register char *s;
	int i;

	progname = argv[0];
	while (argc > 1 && argv[1][0] == '-') {
		switch (argv[1][1]) {
		case 'u':
			/* unix output */
			nascom = 0;
			nl = '\n';
			break;
		case 'e':
			/* fill EPROM. make minimal change */
			zero = 0xFF;
			break;
		case 'd':
			/* displacement at load time */
			disp = atoi(&argv[1][2]);
			break;
		}
		argc--;
		argv++;
	}
	s = "a.out";
	if (argc == 2)
		s = argv[1];
	else if (argc != 1) {
		fprintf(stderr,"usage: %s [flags] [object file]\n",progname);
		stop(-1);
	}
	if (! rd_open(s)) {
		fprintf(stderr,"%s: can't open %s\n",progname,s);
		stop(-1);
	}
	if (nascom) {
		signal(SIGHUP, SIG_IGN);
		signal(SIGINT, SIG_IGN);
		signal(SIGQUIT, stop);
		signal(SIGTERM, stop);
		if (gtty(1, &ttynormal) < 0) {
			fprintf(stderr, "no tty\n");
			stop(-1);
		}
		rawmode++;
		ttyraw = ttynormal;
		ttyraw.sg_flags |= RAW;
		ttyraw.sg_ispeed = B1200;
		ttyraw.sg_ospeed = B1200;
		stty(1, &ttyraw);
		sleep(5);
	}
	rd_ohead(&ohead);
	if (ohead.oh_flags & HF_LINK) {
		fprintf(stderr,"%s: %s contains unresolved references\n",progname,s);
		stop(-1);
	}
	rd_sect(sect, ohead.oh_nsect);
	for (i = 0; i < ohead.oh_nsect; i++) {
		rd_outsect(i);
		pc = sect[i].os_base;
		while (sect[i].os_size) {
			unsigned int sz = 8096, fl;
			extern char *calloc();
			register char *buf;
			char *pbuf;

			if (sz > sect[i].os_size) sz = sect[i].os_size;
			sect[i].os_size -= sz;
			pbuf = buf = calloc(sz, 1);
			if (fl = sect[i].os_flen) {
				if (fl > sz) fl = sz;
				sect[i].os_flen -= fl;

				rd_emit(buf, (long) fl);
			}
			while (sz >= 8) {
				data(8, (int) pc, buf);
				sz -= 8;
				buf += 8;
				pc += 8;
			}
			if (sz > 0) {
				data(sz, (int) pc, buf);
			}
			free(pbuf);
		}
	}
	putchar('.');
	putchar(nl);
	if (nascom)
		sleep(5);
	stop(0);
}

data(nd,pc,buf)
	register char *buf;
	int pc;
{
	register i;

	check = 0;
	pc += disp;
	byte(pc>>8);
	byte(pc);
	for (i = 0; i < nd; i++) {
		putchar(' ');
		byte(*buf++);
	}
	while (i < 8) {
		putchar(' ');
		byte(zero);
		i++;
	}
	putchar(' ');
	byte(check);
	putchar(nl);
}

byte(b) {

	check += b;
	putchar(hex[(b>>4) & 017]);
	putchar(hex[b & 017]);
}

rd_fatal()
{
	fprintf(stderr, "%s: Read error\n", progname);
	stop(-1);
}