changeset 411:2a2e723d4372 default tip

dspanal: new program patchanal2
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 16 Apr 2026 02:13:32 +0000
parents 6ab251771379
children
files .hgignore dspanal/Makefile dspanal/patchanal2.c
diffstat 3 files changed, 143 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Apr 13 08:04:59 2026 +0000
+++ b/.hgignore	Thu Apr 16 02:13:32 2026 +0000
@@ -27,6 +27,7 @@
 ^dspanal/char2bin$
 ^dspanal/char2coff$
 ^dspanal/patchanal$
+^dspanal/patchanal2$
 
 ^fir/fir2freq$
 
--- a/dspanal/Makefile	Mon Apr 13 08:04:59 2026 +0000
+++ b/dspanal/Makefile	Thu Apr 16 02:13:32 2026 +0000
@@ -1,7 +1,7 @@
 CC=	gcc
 CFLAGS=	-O2
 SIMPLE=	char2bin patchanal
-CMPLX=	char2coff
+CMPLX=	char2coff patchanal2
 PROGS=	${SIMPLE} ${CMPLX}
 
 all:	${PROGS}
@@ -15,5 +15,8 @@
 char2coff:	char2coff.o charparse.o coffout.o
 	${CC} ${CFLAGS} -o $@ $^
 
+patchanal2:	charparse.o patchanal2.o
+	${CC} ${CFLAGS} -o $@ $^
+
 clean:
 	rm -f ${PROGS} *.o *errs *.out
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dspanal/patchanal2.c	Thu Apr 16 02:13:32 2026 +0000
@@ -0,0 +1,138 @@
+/*
+ * This program reads a DSP patch file in the form of char array, either
+ * the classic or the dynamic kind, and parses it into sections.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+extern unsigned read_char_file();
+
+static u_char binbuffer[300000];
+static unsigned array_size;
+static u_char *array_ptr, *array_end;
+
+static uint16_t
+get_shortword()
+{
+	uint16_t datum;
+
+	if (array_ptr + 2 > array_end) {
+		fprintf(stderr, "error: parse spills past end of array\n");
+		exit(1);
+	}
+	datum = (array_ptr[1] << 8) | array_ptr[0];
+	array_ptr += 2;
+	return datum;
+}
+
+static uint32_t
+get_longword()
+{
+	uint32_t datum;
+
+	if (array_ptr + 4 > array_end) {
+		fprintf(stderr, "error: parse spills past end of array\n");
+		exit(1);
+	}
+	datum = (array_ptr[3] << 24) | (array_ptr[2] << 16) |
+		(array_ptr[1] << 8) | array_ptr[0];
+	array_ptr += 4;
+	return datum;
+}
+
+static void
+dump_section(dspaddr, size)
+	uint32_t dspaddr, size;
+{
+	uint32_t off;
+	uint16_t word;
+	int i;
+
+	for (off = 0; off < size; ) {
+		printf("%05X:", (unsigned)(dspaddr + off));
+		for (i = 0; i < 8; i++) {
+			if (off >= size)
+				break;
+			word = get_shortword();
+			printf(" %04X", word);
+			off++;
+		}
+		putchar('\n');
+	}
+	putchar('\n');
+}
+
+main(argc, argv)
+	char **argv;
+{
+	uint32_t addr, size;
+	uint16_t word;
+	int opt, dynamic = 0, verbose = 0;
+	extern int optind;
+
+	while ((opt = getopt(argc, argv, "dv")) != EOF) {
+		switch (opt) {
+		case 'd':
+			dynamic++;
+			break;
+		case 'v':
+			verbose++;
+			break;
+		default:
+		usage:
+			fprintf(stderr, "usage: %s [-d] [-v] char-array-file\n",
+				argv[0]);
+			exit(1);
+		}
+	}
+	if (argc != optind + 1)
+		goto usage;
+	array_size = read_char_file(argv[optind], binbuffer, sizeof binbuffer);
+	array_ptr = binbuffer;
+	array_end = array_ptr + array_size;
+	if (get_longword() != 0) {
+		fprintf(stderr, "error: initial tag 0 is missing\n");
+		exit(1);
+	}
+	if (get_longword() != 3) {
+		fprintf(stderr, "error: initial vers 3 is missing\n");
+		exit(1);
+	}
+	for (;;) {
+		size = get_longword();
+		if (size > 0x10000) {
+			fprintf(stderr, "error: section size unreasonable\n");
+			exit(1);
+		}
+		addr = get_longword();
+		printf("size %08lX addr %08lX\n", (u_long) size, (u_long) addr);
+		if (!size)
+			break;
+		if (verbose)
+			dump_section(addr, size);
+		else
+			array_ptr += size << 1;
+		if (dynamic) {
+			word = get_shortword();
+			if (word != 0xDEAD) {
+				fprintf(stderr,
+				"error: extra word is %04X instead of DEAD\n",
+					word);
+				exit(1);
+			}
+		}
+	}
+	if (dynamic) {
+		word = get_shortword();
+		printf("Dynamic patch CRC: %04X\n", word);
+	}
+	if (array_ptr == array_end)
+		printf("Array ends on endmarker, good!\n");
+	else
+		printf("Error: endmarker != end of array!\n");
+	exit(0);
+}