changeset 176:2b38691076b9

fc-e1decode utility written, compiles
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 25 Mar 2017 20:31:01 +0000
parents b002c7cf5d03
children 2133c475f5bd
files .hgignore ringtools/Makefile ringtools/fc-e1decode.c
diffstat 3 files changed, 173 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Sat Mar 25 18:36:37 2017 +0000
+++ b/.hgignore	Sat Mar 25 20:31:01 2017 +0000
@@ -27,6 +27,7 @@
 ^miscutil/fc-vm2hex$
 ^miscutil/imei-luhn$
 
+^ringtools/fc-e1decode$
 ^ringtools/fc-e1gen$
 
 ^rvinterf/asyncshell/fc-shell$
--- a/ringtools/Makefile	Sat Mar 25 18:36:37 2017 +0000
+++ b/ringtools/Makefile	Sat Mar 25 20:31:01 2017 +0000
@@ -1,10 +1,13 @@
 CC=	gcc
 CFLAGS=	-O2
-PROGS=	fc-e1gen
+PROGS=	fc-e1decode fc-e1gen
 INSTBIN=/opt/freecalypso/bin
 
 all:	${PROGS}
 
+fc-e1decode:	fc-e1decode.c
+	${CC} ${CFLAGS} -o $@ $@.c
+
 fc-e1gen:	fc-e1gen.c
 	${CC} ${CFLAGS} -o $@ $@.c
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ringtools/fc-e1decode.c	Sat Mar 25 20:31:01 2017 +0000
@@ -0,0 +1,168 @@
+/*
+ * This program decodes a binary Melody E1 file into the ASCII source format
+ * of our own invention which fc-e1gen accepts as input.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+
+char *infname;
+FILE *inf, *outf;
+
+static unsigned
+get_word()
+{
+	u_char b[2];
+	int i, c;
+
+	for (i = 0; i < 2; i++) {
+		c = getc(inf);
+		if (c < 0) {
+			fprintf(stderr, "error: premature EOF in %s\n",
+				infname);
+			exit(1);
+		}
+		b[i] = c;
+	}
+	return((b[1] << 8) | b[0]);
+}
+
+do_global_osc_set()
+{
+	unsigned word, osc;
+
+	word = get_word();
+	fprintf(outf, "osc-set (%u)", word & 0xFF);
+	for (osc = 0; osc < 8; osc++)
+		if (word & (1 << (osc + 8)))
+			fprintf(outf, " %u", osc);
+	putc('\n', outf);
+	putc('\n', outf);
+}
+
+convert_signed_14bit(u)
+	unsigned u;
+{
+	int i;
+
+	i = u;
+	if (i >= 8192)
+		i -= 16384;
+	return (i);
+}
+
+convert_signed_5bit(u)
+	unsigned u;
+{
+	int i;
+
+	i = u;
+	if (i >= 16)
+		i -= 32;
+	return (i);
+}
+
+process_oscwords(osc, warnflags)
+	unsigned osc, *warnflags;
+{
+	unsigned word0, word1, extraword;
+
+	word0 = get_word();
+	word1 = get_word();
+	if (word1 & 0xF)
+		*warnflags |= 1;
+	fprintf(outf, "osc %u (%u)", osc, word0 & 1);
+	if (word0 & 2) {
+		fprintf(outf, " df %d %u", convert_signed_14bit(word0 >> 2),
+			word1 >> 6);
+	} else {
+		if (word0 & 4)
+			fputs(" sq1", outf);
+		if (word0 & 8)
+			fputs(" sq2", outf);
+		fprintf(outf, " %u %u %u", (word0 >> 4) & 0x3F, word0 >> 10,
+			word1 >> 6);
+	}
+	if (word1 & 0x10) {
+		extraword = get_word();
+		if (extraword & 0xFF)
+			*warnflags |= 2;
+		fprintf(outf, " trem %u %d", (extraword >> 8) & 7,
+			convert_signed_5bit(extraword >> 11));
+	}
+	if (word1 & 0x20) {
+		extraword = get_word();
+		fprintf(outf, " env %u %u %u %u %u", extraword & 0xF,
+			extraword >> 13, (extraword >> 10) & 7,
+			(extraword >> 7) & 7, (extraword >> 4) & 7);
+	}
+}
+
+process_block(timeword)
+	unsigned timeword;
+{
+	unsigned osc, warnflags[8], anywarn;
+
+	fprintf(outf, "time %u\n", timeword & 0xFF);
+	for (osc = 0; osc < 8; osc++) {
+		warnflags[osc] = 0;
+		if (timeword & (1 << (osc + 8)))
+			process_oscwords(osc, warnflags + osc);
+	}
+	putc('\n', outf);
+	anywarn = 0;
+	for (osc = 0; osc < 8; osc++) {
+		if (warnflags[osc] & 1) {
+			fprintf(outf,
+			"# warning: reserved bits set in osc %u word1 above\n",
+				osc);
+			anywarn = 1;
+		}
+		if (warnflags[osc] & 2) {
+			fprintf(outf,
+			"# warning: reserved bits set in osc %u word2 above\n",
+				osc);
+			anywarn = 1;
+		}
+	}
+	if (anywarn)
+		putc('\n', outf);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	unsigned timeword;
+
+	if (argc < 2 || argc > 3) {
+		fprintf(stderr, "usage: %s infile [outfile]\n", argv[0]);
+		exit(1);
+	}
+	infname = argv[1];
+	inf = fopen(infname, "r");
+	if (!inf) {
+		perror(infname);
+		exit(1);
+	}
+	if (argc > 2) {
+		outf = fopen(argv[2], "w");
+		if (!outf) {
+			perror(argv[2]);
+			exit(1);
+		}
+	} else
+		outf = stdout;
+	do_global_osc_set();
+	for (;;) {
+		timeword = get_word();
+		if (timeword == 0)
+			break;
+		process_block(timeword);
+	}
+	fputs("end\n", outf);
+	exit(0);
+}