summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tool/p8bin2hex.c160
-rw-r--r--tool/p8bin2uart.c174
2 files changed, 334 insertions, 0 deletions
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 @@
1/*
2 * PDP-8 format converter.
3 *
4 * Usage: p8bin2hex tape.bin > tape.hex
5 *
6 * Assumes tape.bin is a SIMH-compatible paper tape image in "BIN" or "RIM"
7 * formats.
8 *
9 * RIM format:
10 * 10.000.000 leader/trailer (at least an inch of these)
11 * 01.aaa.aaa address hi (bits 5:0 contain address 11:6)
12 * 00.aaa.aaa address lo (bits 5:0 contain address 5:0)
13 * 00.xxx.xxx data hi (bits 5:0 contain data 11:6)
14 * 00.xxx.xxx data lo (bits 5:0 contain data 5:0)
15 * <repeat any number of [address, data] pairs>
16 *
17 * FIXME: RIM format currently almost always fails with bad checksum
18 *
19 * BIN format:
20 * 10.000.000 leader/trailer (at least an inch of these)
21 * 11.011.000 "field" (bits 6:4 specify address 14:12)
22 * 01.000.010 origin hi bits: bits 5:0 contain origin 11:6
23 * 00.011.100 origin lo bits: bits 5:0 contain origin 5:0
24 * 00.xxx.xxx data hi bits: bits 5:0 contain data word 11:6
25 * 00.xxx.xxx data lo bits: bits 5:0 contain data word 5:0
26 * <repeat any number of [origin, data+] sequences>
27 * 00.xxx.xxx chucksum hi - sum of all data and origin frames, but
28 * 00.xxx.xxx chucksum lo - excluding field and leader/trailer
29 *
30 * Some tapes may contain assembler error messages. These are are text
31 * delimited by 0377 bytes. The BIN loader ignores bytes from starting
32 * at any 0377 byte, until another 0377 byte is seen.
33 */
34
35#include <inttypes.h>
36#include <stdio.h>
37#include <stdlib.h>
38
39uint16_t mem[32768];
40
41int
42load(FILE *fp)
43{
44 enum { Addr, Data, Leader, Fetch, Skip , Start } s = Start;
45 int c = 0, n, v = 0;
46 uint16_t a = 0, d = 0, t = 0, u = 0;
47 for (n = 0; (c = getc(fp)) != EOF; ++n) {
48 switch (s) {
49 case Addr:
50 u += c;
51 a |= c;
52 s = Fetch;
53 break;
54 case Data:
55 u += c;
56 d |= 0x8000 | c;
57 s = Fetch;
58 break;
59 case Fetch:
60 fetch:
61 if (c == 0200) {
62 if ((d & 0x8000) != 0) {
63 if ((d & 07777) != (t & 07777))
64 fprintf(stderr, "\nbad checksum %05o\n", t & 07777);
65 else
66 v = 1;
67 }
68 goto leadout;
69 }
70 t += u;
71 u = 0;
72 if (d & 0x8000) {
73 mem[a] = d & 07777;
74 a = (a & ~07777) | ((a + 1) & 07777);
75 d = 0;
76 }
77 if ((c & 0300) == 0000) {
78 u = c;
79 d = (c & 077) << 6;
80 s = Data;
81 break;
82 }
83 if ((c & 0300) == 0100) {
84 u = c;
85 a = (a & ~07777) | (c & 077) << 6;
86 s = Addr;
87 break;
88 }
89 if ((c & 0307) == 0300) {
90 a = ((c & 0070) << 9) | (a & 07777);
91 break;
92 }
93 if (c == 0377) {
94 s = Skip;
95 break;
96 }
97 break;
98 case Leader:
99 leader:
100 if (c != 0200) {
101 s= Fetch;
102 goto fetch;
103 }
104 break;
105 case Skip:
106 if (c == 0377) {
107 s = Fetch;
108 putchar('\n');
109 } else {
110 putchar(c);
111 }
112 break;
113 case Start:
114 if (c == 0200) {
115 s = Leader;
116 goto leader;
117 }
118 break;
119 }
120 }
121 leadout:
122 while ((c = getc(fp)) != EOF)
123 ;
124 putchar('\n');
125 return v;
126}
127
128void
129dump()
130{
131 printf("// Generated by p8bin2hex");
132 unsigned int nextaddr = -1;
133 for (uint_fast32_t a = 0; a < 32768; ++a) {
134 if (mem[a] == 0) continue;
135 if (nextaddr != a)
136 printf("\n@%x", (unsigned int)a);
137 nextaddr = a + 1;
138 printf(" %03x", mem[a]);
139 }
140 printf("\n");
141}
142
143int
144main(int argc, char *argv[])
145{
146 if (argc != 2) {
147 fprintf(stderr, "usage: p8 filename.bin\n");
148 exit(EXIT_FAILURE);
149 }
150 FILE *fp = fopen(argv[1], "rb");
151 if (!fp) {
152 perror(argv[1]);
153 exit(EXIT_FAILURE);
154 }
155 if (!load(fp))
156 exit(EXIT_FAILURE);
157 fclose(fp);
158 dump();
159 exit(EXIT_SUCCESS);
160}
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 @@
1// vim: set noexpandtab sw=8
2
3/*
4 * PDP-8 format converter.
5 *
6 * Usage: p8bin2hex tape.bin > tape.hex
7 *
8 * Assumes tape.bin is a SIMH-compatible paper tape image in "BIN" or "RIM"
9 * formats.
10 *
11 * RIM format:
12 * 10.000.000 leader/trailer (at least an inch of these)
13 * 01.aaa.aaa address hi (bits 5:0 contain address 11:6)
14 * 00.aaa.aaa address lo (bits 5:0 contain address 5:0)
15 * 00.xxx.xxx data hi (bits 5:0 contain data 11:6)
16 * 00.xxx.xxx data lo (bits 5:0 contain data 5:0)
17 * <repeat any number of [address, data] pairs>
18 *
19 * FIXME: RIM format currently almost always fails with bad checksum
20 *
21 * BIN format:
22 * 10.000.000 leader/trailer (at least an inch of these)
23 * 11.011.000 "field" (bits 6:4 specify address 14:12)
24 * 01.000.010 origin hi bits: bits 5:0 contain origin 11:6
25 * 00.011.100 origin lo bits: bits 5:0 contain origin 5:0
26 * 00.xxx.xxx data hi bits: bits 5:0 contain data word 11:6
27 * 00.xxx.xxx data lo bits: bits 5:0 contain data word 5:0
28 * <repeat any number of [origin, data+] sequences>
29 * 00.xxx.xxx chucksum hi - sum of all data and origin frames, but
30 * 00.xxx.xxx chucksum lo - excluding field and leader/trailer
31 *
32 * Some tapes may contain assembler error messages. These are are text
33 * delimited by 0377 bytes. The BIN loader ignores bytes from starting
34 * at any 0377 byte, until another 0377 byte is seen.
35 */
36
37#include <inttypes.h>
38#include <stdio.h>
39#include <stdlib.h>
40
41uint16_t mem[32768];
42
43int
44load(FILE *fp)
45{
46 enum { Addr, Data, Leader, Fetch, Skip , Start } s = Start;
47 int c = 0, n, v = 0;
48 uint16_t a = 0, d = 0, t = 0, u = 0;
49 for (n = 0; (c = getc(fp)) != EOF; ++n) {
50 switch (s) {
51 case Addr:
52 u += c;
53 a |= c;
54 s = Fetch;
55 break;
56 case Data:
57 u += c;
58 d |= 0x8000 | c;
59 s = Fetch;
60 break;
61 case Fetch:
62 fetch:
63 if (c == 0200) {
64 if ((d & 0x8000) != 0) {
65 if ((d & 07777) != (t & 07777))
66 fprintf(stderr, "\nbad checksum %05o\n", t & 07777);
67 else
68 v = 1;
69 }
70 goto leadout;
71 }
72 t += u;
73 u = 0;
74 if (d & 0x8000) {
75 mem[a] = d & 07777;
76 a = (a & ~07777) | ((a + 1) & 07777);
77 d = 0;
78 }
79 if ((c & 0300) == 0000) {
80 u = c;
81 d = (c & 077) << 6;
82 s = Data;
83 break;
84 }
85 if ((c & 0300) == 0100) {
86 u = c;
87 a = (a & ~07777) | (c & 077) << 6;
88 s = Addr;
89 break;
90 }
91 if ((c & 0307) == 0300) {
92 a = ((c & 0070) << 9) | (a & 07777);
93 break;
94 }
95 if (c == 0377) {
96 s = Skip;
97 break;
98 }
99 break;
100 case Leader:
101 leader:
102 if (c != 0200) {
103 s= Fetch;
104 goto fetch;
105 }
106 break;
107 case Skip:
108 if (c == 0377)
109 s = Fetch;
110 break;
111 case Start:
112 if (c == 0200) {
113 s = Leader;
114 goto leader;
115 }
116 break;
117 }
118 }
119 leadout:
120 while ((c = getc(fp)) != EOF)
121 ;
122 return v;
123}
124
125void
126dump()
127{
128 unsigned int linesize = 0;
129 unsigned int nextaddr = 0;
130 for (uint_fast32_t a = 0; a < 32768; ++a) {
131 if (mem[a] == 0) continue;
132 if (nextaddr != a) {
133 if (nextaddr + 1 == a)
134 linesize += printf("=");
135 else
136 linesize += printf("!%x", (unsigned int)(a - nextaddr));
137 if (linesize > 1018) {
138 printf("\n");
139 linesize = 0;
140 } else {
141 linesize += printf(" ");
142 }
143 }
144 linesize += printf("=%x", mem[a]);
145 if (linesize > 1018) {
146 printf("\n");
147 linesize = 0;
148 } else {
149 linesize += printf(" ");
150 }
151 nextaddr = a + 1;
152 }
153 if (nextaddr != 32768)
154 printf("!%x\n", (unsigned int)(32768 - nextaddr));
155}
156
157int
158main(int argc, char *argv[])
159{
160 if (argc != 2) {
161 fprintf(stderr, "usage: p8 filename.bin\n");
162 exit(EXIT_FAILURE);
163 }
164 FILE *fp = fopen(argv[1], "rb");
165 if (!fp) {
166 perror(argv[1]);
167 exit(EXIT_FAILURE);
168 }
169 if (!load(fp))
170 exit(EXIT_FAILURE);
171 fclose(fp);
172 dump();
173 exit(EXIT_SUCCESS);
174}