From 1b3915e330384ea0aacd59e8f9152288dcf70c50 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sun, 13 Mar 2022 16:52:16 -0700 Subject: Import p8bin2* tools into repo. --- tool/p8bin2hex.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++ tool/p8bin2uart.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 334 insertions(+) create mode 100644 tool/p8bin2hex.c create mode 100644 tool/p8bin2uart.c diff --git a/tool/p8bin2hex.c b/tool/p8bin2hex.c new file mode 100644 index 0000000..4ef10fc --- /dev/null +++ b/tool/p8bin2hex.c @@ -0,0 +1,160 @@ +/* + * PDP-8 format converter. + * + * Usage: p8bin2hex tape.bin > tape.hex + * + * Assumes tape.bin is a SIMH-compatible paper tape image in "BIN" or "RIM" + * formats. + * + * RIM format: + * 10.000.000 leader/trailer (at least an inch of these) + * 01.aaa.aaa address hi (bits 5:0 contain address 11:6) + * 00.aaa.aaa address lo (bits 5:0 contain address 5:0) + * 00.xxx.xxx data hi (bits 5:0 contain data 11:6) + * 00.xxx.xxx data lo (bits 5:0 contain data 5:0) + * + * + * FIXME: RIM format currently almost always fails with bad checksum + * + * BIN format: + * 10.000.000 leader/trailer (at least an inch of these) + * 11.011.000 "field" (bits 6:4 specify address 14:12) + * 01.000.010 origin hi bits: bits 5:0 contain origin 11:6 + * 00.011.100 origin lo bits: bits 5:0 contain origin 5:0 + * 00.xxx.xxx data hi bits: bits 5:0 contain data word 11:6 + * 00.xxx.xxx data lo bits: bits 5:0 contain data word 5:0 + * + * 00.xxx.xxx chucksum hi - sum of all data and origin frames, but + * 00.xxx.xxx chucksum lo - excluding field and leader/trailer + * + * Some tapes may contain assembler error messages. These are are text + * delimited by 0377 bytes. The BIN loader ignores bytes from starting + * at any 0377 byte, until another 0377 byte is seen. + */ + +#include +#include +#include + +uint16_t mem[32768]; + +int +load(FILE *fp) +{ + enum { Addr, Data, Leader, Fetch, Skip , Start } s = Start; + int c = 0, n, v = 0; + uint16_t a = 0, d = 0, t = 0, u = 0; + for (n = 0; (c = getc(fp)) != EOF; ++n) { + switch (s) { + case Addr: + u += c; + a |= c; + s = Fetch; + break; + case Data: + u += c; + d |= 0x8000 | c; + s = Fetch; + break; + case Fetch: + fetch: + if (c == 0200) { + if ((d & 0x8000) != 0) { + if ((d & 07777) != (t & 07777)) + fprintf(stderr, "\nbad checksum %05o\n", t & 07777); + else + v = 1; + } + goto leadout; + } + t += u; + u = 0; + if (d & 0x8000) { + mem[a] = d & 07777; + a = (a & ~07777) | ((a + 1) & 07777); + d = 0; + } + if ((c & 0300) == 0000) { + u = c; + d = (c & 077) << 6; + s = Data; + break; + } + if ((c & 0300) == 0100) { + u = c; + a = (a & ~07777) | (c & 077) << 6; + s = Addr; + break; + } + if ((c & 0307) == 0300) { + a = ((c & 0070) << 9) | (a & 07777); + break; + } + if (c == 0377) { + s = Skip; + break; + } + break; + case Leader: + leader: + if (c != 0200) { + s= Fetch; + goto fetch; + } + break; + case Skip: + if (c == 0377) { + s = Fetch; + putchar('\n'); + } else { + putchar(c); + } + break; + case Start: + if (c == 0200) { + s = Leader; + goto leader; + } + break; + } + } + leadout: + while ((c = getc(fp)) != EOF) + ; + putchar('\n'); + return v; +} + +void +dump() +{ + printf("// Generated by p8bin2hex"); + unsigned int nextaddr = -1; + for (uint_fast32_t a = 0; a < 32768; ++a) { + if (mem[a] == 0) continue; + if (nextaddr != a) + printf("\n@%x", (unsigned int)a); + nextaddr = a + 1; + printf(" %03x", mem[a]); + } + printf("\n"); +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "usage: p8 filename.bin\n"); + exit(EXIT_FAILURE); + } + FILE *fp = fopen(argv[1], "rb"); + if (!fp) { + perror(argv[1]); + exit(EXIT_FAILURE); + } + if (!load(fp)) + exit(EXIT_FAILURE); + fclose(fp); + dump(); + exit(EXIT_SUCCESS); +} diff --git a/tool/p8bin2uart.c b/tool/p8bin2uart.c new file mode 100644 index 0000000..13ac38c --- /dev/null +++ b/tool/p8bin2uart.c @@ -0,0 +1,174 @@ +// vim: set noexpandtab sw=8 + +/* + * PDP-8 format converter. + * + * Usage: p8bin2hex tape.bin > tape.hex + * + * Assumes tape.bin is a SIMH-compatible paper tape image in "BIN" or "RIM" + * formats. + * + * RIM format: + * 10.000.000 leader/trailer (at least an inch of these) + * 01.aaa.aaa address hi (bits 5:0 contain address 11:6) + * 00.aaa.aaa address lo (bits 5:0 contain address 5:0) + * 00.xxx.xxx data hi (bits 5:0 contain data 11:6) + * 00.xxx.xxx data lo (bits 5:0 contain data 5:0) + * + * + * FIXME: RIM format currently almost always fails with bad checksum + * + * BIN format: + * 10.000.000 leader/trailer (at least an inch of these) + * 11.011.000 "field" (bits 6:4 specify address 14:12) + * 01.000.010 origin hi bits: bits 5:0 contain origin 11:6 + * 00.011.100 origin lo bits: bits 5:0 contain origin 5:0 + * 00.xxx.xxx data hi bits: bits 5:0 contain data word 11:6 + * 00.xxx.xxx data lo bits: bits 5:0 contain data word 5:0 + * + * 00.xxx.xxx chucksum hi - sum of all data and origin frames, but + * 00.xxx.xxx chucksum lo - excluding field and leader/trailer + * + * Some tapes may contain assembler error messages. These are are text + * delimited by 0377 bytes. The BIN loader ignores bytes from starting + * at any 0377 byte, until another 0377 byte is seen. + */ + +#include +#include +#include + +uint16_t mem[32768]; + +int +load(FILE *fp) +{ + enum { Addr, Data, Leader, Fetch, Skip , Start } s = Start; + int c = 0, n, v = 0; + uint16_t a = 0, d = 0, t = 0, u = 0; + for (n = 0; (c = getc(fp)) != EOF; ++n) { + switch (s) { + case Addr: + u += c; + a |= c; + s = Fetch; + break; + case Data: + u += c; + d |= 0x8000 | c; + s = Fetch; + break; + case Fetch: + fetch: + if (c == 0200) { + if ((d & 0x8000) != 0) { + if ((d & 07777) != (t & 07777)) + fprintf(stderr, "\nbad checksum %05o\n", t & 07777); + else + v = 1; + } + goto leadout; + } + t += u; + u = 0; + if (d & 0x8000) { + mem[a] = d & 07777; + a = (a & ~07777) | ((a + 1) & 07777); + d = 0; + } + if ((c & 0300) == 0000) { + u = c; + d = (c & 077) << 6; + s = Data; + break; + } + if ((c & 0300) == 0100) { + u = c; + a = (a & ~07777) | (c & 077) << 6; + s = Addr; + break; + } + if ((c & 0307) == 0300) { + a = ((c & 0070) << 9) | (a & 07777); + break; + } + if (c == 0377) { + s = Skip; + break; + } + break; + case Leader: + leader: + if (c != 0200) { + s= Fetch; + goto fetch; + } + break; + case Skip: + if (c == 0377) + s = Fetch; + break; + case Start: + if (c == 0200) { + s = Leader; + goto leader; + } + break; + } + } + leadout: + while ((c = getc(fp)) != EOF) + ; + return v; +} + +void +dump() +{ + unsigned int linesize = 0; + unsigned int nextaddr = 0; + for (uint_fast32_t a = 0; a < 32768; ++a) { + if (mem[a] == 0) continue; + if (nextaddr != a) { + if (nextaddr + 1 == a) + linesize += printf("="); + else + linesize += printf("!%x", (unsigned int)(a - nextaddr)); + if (linesize > 1018) { + printf("\n"); + linesize = 0; + } else { + linesize += printf(" "); + } + } + linesize += printf("=%x", mem[a]); + if (linesize > 1018) { + printf("\n"); + linesize = 0; + } else { + linesize += printf(" "); + } + nextaddr = a + 1; + } + if (nextaddr != 32768) + printf("!%x\n", (unsigned int)(32768 - nextaddr)); +} + +int +main(int argc, char *argv[]) +{ + if (argc != 2) { + fprintf(stderr, "usage: p8 filename.bin\n"); + exit(EXIT_FAILURE); + } + FILE *fp = fopen(argv[1], "rb"); + if (!fp) { + perror(argv[1]); + exit(EXIT_FAILURE); + } + if (!load(fp)) + exit(EXIT_FAILURE); + fclose(fp); + dump(); + exit(EXIT_SUCCESS); +} -- cgit v1.2.3