view ffstools/tiaud/decomp.c @ 686:752aef91cc95

fc-loadtool batch mode extended to support single commands
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 11 Mar 2020 00:01:58 +0000
parents 568e2a2b49c8
children c458e33060bf
line wrap: on
line source

/*
 * This utility decompiles a binary /aud/*.cfg file read out of FFS
 * into our ASCII text representation.
 */

#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdint.h>
#include <endian.h>
#include <stdlib.h>
#include <unistd.h>
#include "binstruct.h"

struct audio_cfg_bin bin;
FILE *outf;

read_bin_file(filename)
	char *filename;
{
	int fd;
	struct stat st;

	fd = open(filename, O_RDONLY);
	if (fd < 0) {
		perror(filename);
		exit(1);
	}
	fstat(fd, &st);
	if (!S_ISREG(st.st_mode)) {
		fprintf(stderr, "%s is not a regular file\n", filename);
		exit(1);
	}
	if (st.st_size != sizeof(struct audio_cfg_bin)) {
		fprintf(stderr, "%s has the wrong length\n", filename);
		exit(1);
	}
	read(fd, &bin, sizeof bin);
	close(fd);
}

emit_fir(table)
	uint16_t *table;
{
	int i;

	for (i = 0; i < 31; i++) {
		if ((i % 8) == 0)
			fprintf(outf, "\tfir %2d", i);
		fprintf(outf, " 0x%04X", le16toh(table[i]));
		if (i == 7 || i == 15 || i == 23 || i == 30)
			putc('\n', outf);
	}
}

emit_ascii()
{
	int i;

	fprintf(outf, "voice-path %u\n", bin.voice_path);

	switch (bin.mic_mode) {
	case AUDIO_MICROPHONE_HANDHELD:
		fprintf(outf, "mic default {\n");
		break;
	case AUDIO_MICROPHONE_HANDFREE:
		fprintf(outf, "mic aux {\n");
		break;
	case AUDIO_MICROPHONE_HEADSET:
		fprintf(outf, "mic headset {\n");
		break;
	default:
		fprintf(stderr, "error: unknown microphone mode 0x%02X\n",
			bin.mic_mode);
		exit(1);
	}
	fprintf(outf, "\tgain %d\n", bin.mic_bytes[0]);
	if (bin.mic_mode == AUDIO_MICROPHONE_HANDFREE) {
		fprintf(outf, "\textra-gain %d\n", bin.mic_bytes[1]);
		fprintf(outf, "\toutput-bias %d\n", bin.mic_bytes[2]);
	} else
		fprintf(outf, "\toutput-bias %d\n", bin.mic_bytes[1]);
	emit_fir(bin.mic_fir);
	fputs("}\n", outf);

	switch (bin.speaker_mode) {
	case AUDIO_SPEAKER_HANDHELD:
		fprintf(outf, "speaker ear {\n");
		break;
	case AUDIO_SPEAKER_HANDFREE:
		fprintf(outf, "speaker aux {\n");
		break;
	case AUDIO_SPEAKER_HEADSET:
		fprintf(outf, "speaker headset {\n");
		break;
	case AUDIO_SPEAKER_BUZZER:
		fprintf(outf, "speaker buzzer {\n");
		break;
	case AUDIO_SPEAKER_HANDHELD_HANDFREE:
		fprintf(outf, "speaker ear+aux {\n");
		break;
	default:
		fprintf(stderr, "error: unknown speaker mode 0x%02X\n",
			bin.speaker_mode);
		exit(1);
	}
	if (bin.speaker_mode != AUDIO_SPEAKER_BUZZER) {
		fprintf(outf, "\tgain %d\n", bin.speaker_bytes[0]);
		fprintf(outf, "\taudio-filter %d\n", bin.speaker_bytes[1]);
		emit_fir(bin.speaker_fir);
	} else
		fprintf(outf, "\tactivate %d\n", bin.speaker_bytes[0]);
	fputs("}\n", outf);

	fprintf(outf, "sidetone %d\n", bin.sidetone_gain);
	fputs("aec", outf);
	for (i = 0; i < 5; i++) {
		putc(' ', outf);
		if (bin.aec_words[i])
			fprintf(outf, "0x%X", le16toh(bin.aec_words[i]));
		else
			putc('0', outf);
	}
	putc('\n', outf);
}

main(argc, argv)
	char **argv;
{
	if (argc < 2 || argc > 3) {
		fprintf(stderr, "usage: %s infile [outfile]\n", argv[0]);
		exit(1);
	}
	read_bin_file(argv[1]);
	if (argc > 2) {
		outf = fopen(argv[2], "w");
		if (!outf) {
			perror(argv[2]);
			exit(1);
		}
	} else
		outf = stdout;
	emit_ascii();
	exit(0);
}