view d144/edata-input-compile.c @ 54:8deebf9c410a

d144: "decompile" binary input format into ASCII
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 25 Sep 2024 04:32:32 +0000
parents 4681ad8483d6
children
line wrap: on
line source

/*
 * This program compiles E-data input from our handcrafting format
 * into the binary format that will be read by itt-ater-16.
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#define	MAX_FIELDS	8

static char *infname, *outfname;
static FILE *inf, *outf;

static int lineno;
static char linebuf[256];
static char *fields[MAX_FIELDS];
static unsigned nfields;

static uint8_t frame_nibbles[72];
static unsigned subframe_count;

static int
get_line()
{
	char *cp;

	if (!fgets(linebuf, sizeof linebuf, inf))
		return 1;
	lineno++;
	if (!index(linebuf, '\n')) {
		fprintf(stderr, "%s line %d: too long or missing newline\n",
			infname, lineno);
		exit(1);
	}
	nfields = 0;
	for (cp = linebuf; ; ) {
		while (isspace(*cp))
			cp++;
		if (*cp == '\0' || *cp == '#')
			break;
		if (nfields >= MAX_FIELDS) {
			fprintf(stderr, "%s line %d: too many fields\n",
				infname, lineno);
			exit(1);
		}
		fields[nfields++] = cp;
		while (*cp && !isspace(*cp))
			cp++;
		if (*cp)
			*cp++ = '\0';
	}
	return 0;
}

static int
get_line_nonempty()
{
	int rc;

	for (;;) {
		rc = get_line();
		if (rc)
			return rc;
		if (nfields)
			return 0;
	}
}

static int
decode_hex_digit(c)
{
	if (isdigit(c))
		return c - '0';
	else if (isupper(c))
		return c - 'A' + 10;
	else
		return c - 'a' + 10;
}

static void
bits_line()
{
	uint8_t *op;
	char *cp;
	unsigned n;

	if (nfields != 2) {
		fprintf(stderr, "%s line %d: bits command takes one argument\n",
			infname, lineno);
		exit(1);
	}
	if (strlen(fields[1]) != 9) {
		fprintf(stderr, "%s line %d: bits argument has wrong length\n",
			infname, lineno);
		exit(1);
	}
	if (subframe_count >= 8) {
		fprintf(stderr,
		"%s line %d: 8 subframes already given, can't have more\n",
			infname, lineno);
		exit(1);
	}
	op = frame_nibbles + subframe_count * 9;
	cp = fields[1];
	for (n = 0; n < 9; n++) {
		if (!isxdigit(*cp)) {
			fprintf(stderr,
				"%s line %d: bits argument is not valid hex\n",
				infname, lineno);
			exit(1);
		}
		*op++ = decode_hex_digit(*cp++);
	}
	subframe_count++;
}

static void
frame_line()
{
	uint8_t bin[38], m_bits[2];
	unsigned n, i;

	if (nfields != 2) {
		fprintf(stderr,
			"%s line %d: frame command takes one argument\n",
			infname, lineno);
		exit(1);
	}
	for (n = 0; n < 2; n++) {
		switch (fields[1][n]) {
		case '0':
			m_bits[n] = 0;
			break;
		case '1':
			m_bits[n] = 1;
			break;
		default:
		bad_arg:
			fprintf(stderr,
				"%s line %d: invalid M-bits argument \"%s\"\n",
				infname, lineno, fields[1]);
			exit(1);
		}
	}
	if (fields[1][2])
		goto bad_arg;

	if (subframe_count != 8) {
		fprintf(stderr,
			"%s line %d: not preceded by exactly 8 subframes\n",
			infname, lineno);
		exit(1);
	}
	bin[0] = 0xD4;
	bin[1] = (m_bits[0] << 1) | m_bits[1];
	i = 0;
	for (n = 0; n < 36; n++) {
		bin[n+2] = (frame_nibbles[i] << 4) | frame_nibbles[i+1];
		i += 2;
	}
	fwrite(bin, 1, 38, outf);

	subframe_count = 0;
}

main(argc, argv)
	char **argv;
{
	int rc;

	if (argc != 3) {
		fprintf(stderr, "usage: %s input.src output.bin\n", argv[0]);
		exit(1);
	}
	infname = argv[1];
	outfname = argv[2];

	inf = fopen(infname, "r");
	if (!inf) {
		perror(infname);
		exit(1);
	}
	outf = fopen(outfname, "w");
	if (!outf) {
		perror(outfname);
		exit(1);
	}

	for (;;) {
		rc = get_line_nonempty();
		if (rc)
			break;
		if (!strcasecmp(fields[0], "bits"))
			bits_line();
		else if (!strcasecmp(fields[0], "frame"))
			frame_line();
		else {
			fprintf(stderr,
				"%s line %d: non-understood keyword \"%s\"\n",
				infname, lineno, fields[0]);
			exit(1);
		}
	}
	exit(0);
}