First Commit of my working state
[simh.git] / Ibm1130 / utils / bindump.c
CommitLineData
196ba1fc
PH
1/*\r
2 * (C) Copyright 2002, Brian Knittel.\r
3 * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN\r
4 * RISK basis, there is no warranty of fitness for any purpose, and the rest of the\r
5 * usual yada-yada. Please keep this notice and the copyright in any distributions\r
6 * or modifications.\r
7 *\r
8 * This is not a supported product, but I welcome bug reports and fixes.\r
9 * Mail to sim@ibm1130.org\r
10 */\r
11\r
12// ---------------------------------------------------------------------------------\r
13// BINDUMP - dumps card deck files in assembler object format\r
14//\r
15// Usage:\r
16/// bindump deckfile lists object header info & sector break cards\r
17// bindump -v deckfile lists object data records as well\r
18// bindump -p deckfile for system program, lists phase IDs in the deck\r
19// bindump -s deckfile >outfile for system program, sorts the phases & writes to stdout\r
20\r
21#include <stdio.h>\r
22#include <stdlib.h>\r
23#ifdef _WIN32\r
24# include <windows.h>\r
25# include <io.h>\r
26# include <fcntl.h>\r
27#endif\r
28\r
29#include "util_io.h"\r
30\r
31#ifndef TRUE\r
32 #define BOOL int\r
33 #define TRUE 1\r
34 #define FALSE 0\r
35#endif\r
36\r
37typedef enum {R_ABSOLUTE = 0, R_RELATIVE = 1, R_LIBF = 2, R_CALL = 3} RELOC;\r
38\r
39BOOL verbose = FALSE;\r
40BOOL phid = FALSE;\r
41BOOL sort = FALSE;\r
42unsigned short card[80], buf[54], cardtype;\r
43\r
44// bindump - dump a binary (card format) deck to verify sbrks, etc\r
45\r
46void bail (char *msg);\r
47void dump (char *fname);\r
48void dump_data (char *fname);\r
49void dump_phids (char *fname);\r
50char *getname (unsigned short *ptr);\r
51char *getseq (void);\r
52int hollerith_to_ascii (unsigned short h);\r
53void process (char *fname);\r
54void show_raw (char *name);\r
55void show_data (void);\r
56void show_core (void);\r
57void show_endc (void);\r
58void show_81 (void);\r
59void show_main (void);\r
60void show_sub (void);\r
61void show_ils (void);\r
62void show_iss (void);\r
63void show_end (void);\r
64void sort_phases (char *fname);\r
65void trim (char *s);\r
66void unpack (unsigned short *card, unsigned short *buf);\r
67void verify_checksum(unsigned short *buf);\r
68\r
69int main (int argc, char **argv)\r
70{\r
71 char *arg;\r
72 static char usestr[] = "Usage: bindump [-psv] filename...";\r
73 int i;\r
74\r
75 for (i = 1; i < argc; i++) {\r
76 arg = argv[i];\r
77 if (*arg == '-') {\r
78 arg++;\r
79 while (*arg) {\r
80 switch (*arg++) {\r
81 case 'v':\r
82 verbose = TRUE;\r
83 break;\r
84 case 'p':\r
85 phid = TRUE; // print only phase ID's\r
86 break;\r
87 case 's':\r
88 sort = TRUE; // sort deck by phases, writing to stdout\r
89 break;\r
90 default:\r
91 bail(usestr);\r
92 }\r
93 }\r
94 }\r
95 }\r
96\r
97 for (i = 1; i < argc; i++) {\r
98 arg = argv[i];\r
99 if (*arg != '-')\r
100 process(arg);\r
101 }\r
102 return 0;\r
103}\r
104\r
105void process (char *nm)\r
106{\r
107#ifdef _WIN32\r
108 WIN32_FIND_DATA fd;\r
109 HANDLE hFind;\r
110 char *c, buf[256];\r
111\r
112 if (strchr(nm, '*') == NULL && strchr(nm, '?') == NULL)\r
113 dump(nm);\r
114\r
115 else if ((hFind = FindFirstFile(nm, &fd)) == INVALID_HANDLE_VALUE)\r
116 fprintf(stderr, "No files matching '%s'\n", nm);\r
117\r
118 else {\r
119 if ((c = strrchr(nm, '\\')) == NULL)\r
120 c = strrchr(nm, ':');\r
121\r
122 do {\r
123 if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\r
124 continue;\r
125\r
126 if (c == NULL)\r
127 dump(fd.cFileName);\r
128 else {\r
129 strcpy(buf, nm);\r
130 strcpy(buf + (c-nm+1), fd.cFileName);\r
131 dump(buf);\r
132 }\r
133 \r
134 } while (FindNextFile(hFind, &fd));\r
135\r
136 FindClose(hFind);\r
137 }\r
138#else\r
139 dump(nm); // on unices, sh globs for us\r
140#endif\r
141}\r
142\r
143void dump (char *fname)\r
144{\r
145 if (sort)\r
146 sort_phases(fname);\r
147 else if (phid)\r
148 dump_phids(fname);\r
149 else\r
150 dump_data(fname);\r
151}\r
152\r
153struct tag_card {\r
154 int phid, seq;\r
155 unsigned short card[80];\r
156};\r
157\r
158int cardcomp (const void *a, const void *b)\r
159{\r
160 short diff;\r
161\r
162 diff = ((struct tag_card *) a)->phid - ((struct tag_card *) b)->phid;\r
163\r
164 return diff ? diff : (((struct tag_card *) a)->seq - ((struct tag_card *) b)->seq);\r
165}\r
166\r
167void sort_phases (char *fname)\r
168{\r
169 int i, ncards, cardtype, len, seq = 0, phid;\r
170 struct tag_card *deck;\r
171 FILE *fd;\r
172 BOOL saw_sbrk = TRUE;\r
173\r
174 if ((fd = fopen(fname, "rb")) == NULL) {\r
175 perror(fname);\r
176 return;\r
177 }\r
178\r
179 fseek(fd, 0, SEEK_END);\r
180 len = ftell(fd); // get length of file\r
181 fseek(fd, 0, SEEK_SET);\r
182\r
183 if (len <= 0 || (len % 160) != 0) {\r
184 fprintf(stderr, "%s is not a binard deck image\n");\r
185 fclose(fd);\r
186 return;\r
187 }\r
188\r
189 ncards = len / 160;\r
190\r
191 if ((deck = (struct tag_card *) malloc(ncards*sizeof(struct tag_card))) == NULL) {\r
192 fprintf(stderr, "%s: can't sort, insufficient memory\n");\r
193 fclose(fd);\r
194 return;\r
195 }\r
196\r
197 phid = 0;\r
198 for (i = 0; i < ncards; i++) {\r
199 if (fxread(deck[i].card, sizeof(card[0]), 80, fd) != 80) {\r
200 free(deck);\r
201 fprintf(stderr, "%s: error reading deck\n");\r
202 fclose(fd);\r
203 return;\r
204 }\r
205\r
206 unpack(deck[i].card, buf);\r
207 deck[i].seq = seq++;\r
208 deck[i].phid = phid;\r
209\r
210 verify_checksum(buf);\r
211\r
212 cardtype = (buf[2] >> 8) & 0xFF;\r
213\r
214 if (cardtype == 1 || cardtype == 2) { // start of deck is same as sector break\r
215 saw_sbrk = TRUE;\r
216 }\r
217 else if (cardtype == 0) {\r
218 fprintf(stderr, "%s is a core image deck\n");\r
219 free(deck);\r
220 fclose(fd);\r
221 return;\r
222 }\r
223 else if (cardtype == 0x0A && saw_sbrk) {\r
224 phid = (int) (signed short) buf[10];\r
225 if (phid < 0)\r
226 phid = -phid;\r
227\r
228 deck[i].phid = phid; // this belongs to the new phase\r
229 deck[i-1].phid = phid; // as does previous card\r
230 saw_sbrk = FALSE;\r
231 }\r
232 }\r
233 fclose(fd);\r
234\r
235 qsort(deck, ncards, sizeof(struct tag_card), cardcomp); // sort the deck\r
236\r
237#ifdef _WIN32\r
238 _setmode(_fileno(stdout), _O_BINARY); // set standard output to binary mode\r
239#endif\r
240\r
241 for (i = 0; i < ncards; i++) // write to stdout\r
242 fxwrite(deck[i].card, sizeof(card[0]), 80, stdout);\r
243\r
244 free(deck);\r
245}\r
246\r
247void dump_phids (char *fname)\r
248{\r
249 FILE *fp;\r
250 BOOL first = TRUE;\r
251 BOOL saw_sbrk = TRUE, neg;\r
252 short id;\r
253\r
254 if ((fp = fopen(fname, "rb")) == NULL) {\r
255 perror(fname);\r
256 return;\r
257 }\r
258 \r
259 printf("\n%s:\n", fname);\r
260\r
261 while (fxread(card, sizeof(card[0]), 80, fp) > 0) {\r
262 unpack(card, buf);\r
263 verify_checksum(buf);\r
264\r
265 cardtype = (buf[2] >> 8) & 0xFF;\r
266\r
267 if (cardtype == 1 && ! first) { // sector break\r
268 saw_sbrk = TRUE;\r
269 continue;\r
270 }\r
271 else {\r
272 switch (cardtype) {\r
273 case 0x00:\r
274 printf(" This is a core image deck\n");\r
275 goto done;\r
276 break;\r
277 case 0x01:\r
278 case 0x02:\r
279 case 0x03:\r
280 case 0x04:\r
281 case 0x05:\r
282 case 0x06:\r
283 case 0x07:\r
284 case 0x0F:\r
285 break;\r
286\r
287 case 0x0A:\r
288 if (saw_sbrk) {\r
289 id = buf[10];\r
290 if (id < 0)\r
291 id = -id, neg = TRUE;\r
292 else\r
293 neg = FALSE;\r
294 printf(" : %3d / %02x%s\n", id, id, neg ? " (neg)" : "");\r
295 saw_sbrk = FALSE;\r
296 }\r
297 break;\r
298\r
299 default:\r
300 show_raw("??? ");\r
301 }\r
302 }\r
303done:\r
304 first = FALSE;\r
305 }\r
306\r
307 fclose(fp);\r
308}\r
309\r
310void dump_data (char *fname)\r
311{\r
312 FILE *fp;\r
313 BOOL first = TRUE;\r
314 char str[80];\r
315 int i;\r
316\r
317 if ((fp = fopen(fname, "rb")) == NULL) {\r
318 perror(fname);\r
319 return;\r
320 }\r
321 \r
322 printf("\n%s:\n", fname);\r
323\r
324 while (fxread(card, sizeof(card[0]), 80, fp) > 0) {\r
325 unpack(card, buf);\r
326 verify_checksum(buf);\r
327\r
328 cardtype = (buf[2] >> 8) & 0xFF;\r
329\r
330 if (cardtype == 1 && ! first) { // sector break\r
331 for (i = 4; i < 72; i++)\r
332 str[i] = hollerith_to_ascii(card[i]);\r
333\r
334 str[i] = '\0';\r
335 trim(str+4);\r
336 printf("*SBRK %s\n", str+4);\r
337 continue;\r
338 }\r
339 else {\r
340 switch (cardtype) {\r
341 case 0x00:\r
342 if (first)\r
343 show_raw("CORE");\r
344 if (verbose)\r
345 show_core();\r
346 break;\r
347\r
348 case 0x01:\r
349 show_raw("ABS ");\r
350 show_main();\r
351 break;\r
352 case 0x02:\r
353 show_raw("REL ");\r
354 show_main();\r
355 break;\r
356 case 0x03:\r
357 show_raw("LIB ");\r
358 show_sub();\r
359 break;\r
360 case 0x04:\r
361 show_raw("SUB ");\r
362 show_sub();\r
363 break;\r
364 case 0x05:\r
365 show_raw("ISSL");\r
366 show_iss();\r
367 break;\r
368 case 0x06:\r
369 show_raw("ISSC");\r
370 show_iss();\r
371 break;\r
372 case 0x07:\r
373 show_raw("ILS ");\r
374 show_ils();\r
375 break;\r
376 case 0x0F:\r
377 show_raw("END ");\r
378 show_end();\r
379 break;\r
380 case 0x80:\r
381 show_raw("ENDC");\r
382 show_endc();\r
383 break;\r
384 case 0x81:\r
385 show_raw("81 ");\r
386 show_81();\r
387 break;\r
388 case 0x0A:\r
389 if (verbose)\r
390 show_data();\r
391 break;\r
392 default:\r
393 show_raw("??? ");\r
394 }\r
395 }\r
396\r
397 first = FALSE;\r
398 }\r
399\r
400 fclose(fp);\r
401}\r
402\r
403void show_data (void)\r
404{\r
405 int i, n, jrel, rflag, nout, ch, reloc;\r
406 BOOL first = TRUE;\r
407\r
408 n = buf[2] & 0x00FF;\r
409\r
410 printf("%04x: ", buf[0]);\r
411\r
412 jrel = 3;\r
413 nout = 0;\r
414 rflag = buf[jrel++];\r
415 for (i = 0; i < n; i++) {\r
416 if (nout >= 8) {\r
417 rflag = buf[jrel++];\r
418 if (first) {\r
419 printf(" %s", getseq());\r
420 first = FALSE;\r
421 }\r
422 printf("\n ");\r
423 nout = 0;\r
424 }\r
425 reloc = (rflag >> 14) & 0x03;\r
426 ch = (reloc == R_ABSOLUTE) ? ' ' :\r
427 (reloc == R_RELATIVE) ? 'R' :\r
428 (reloc == R_LIBF) ? 'L' : '@';\r
429\r
430 printf("%04x%c ", buf[9+i], ch);\r
431 rflag <<= 2;\r
432 nout++;\r
433 }\r
434 putchar('\n');\r
435}\r
436\r
437void show_core (void)\r
438{\r
439 int i, n, nout;\r
440 BOOL first = TRUE;\r
441\r
442 n = buf[2] & 0x00FF;\r
443\r
444 printf("%04x: ", buf[0]);\r
445\r
446 nout = 0;\r
447 for (i = 0; i < n; i++) {\r
448 if (nout >= 8) {\r
449 if (first) {\r
450 printf(" %s", getseq());\r
451 first = FALSE;\r
452 }\r
453 printf("\n ");\r
454 nout = 0;\r
455 }\r
456 printf("%04x ", buf[9+i]);\r
457 nout++;\r
458 }\r
459 putchar('\n');\r
460}\r
461\r
462void info (int i, char *nm, char type)\r
463{\r
464 if (nm)\r
465 printf("%s ", nm);\r
466\r
467 switch (type) {\r
468 case 'd':\r
469 printf("%d ", buf[i]);\r
470 break;\r
471\r
472 case 'x':\r
473 printf("%04x ", buf[i]);\r
474 break;\r
475\r
476 case 'b':\r
477 printf("%02x ", buf[i] & 0xFF);\r
478 break;\r
479\r
480 case 'n':\r
481 printf("%s ", getname(buf+i));\r
482 break;\r
483\r
484 default:\r
485 bail("BAD TYPE");\r
486 }\r
487}\r
488\r
489void show_main (void)\r
490{\r
491 printf(" ");\r
492 info(2, "prec", 'b');\r
493 info(4, "common", 'd');\r
494 info(6, "work", 'd');\r
495 info(8, "files", 'd');\r
496 info(9, "name", 'n');\r
497 info(11, "pta", 'x');\r
498 putchar('\n');\r
499}\r
500\r
501void show_sub (void)\r
502{\r
503 int i, n;\r
504\r
505 printf(" ");\r
506 info( 2, "prec", 'b');\r
507\r
508 n = buf[5] / 3;\r
509 for (i = 0; i < n; i++) {\r
510 info( 9+3*i, "ent", 'n');\r
511 info(11+3*i, NULL, 'x');\r
512 }\r
513\r
514 putchar('\n');\r
515}\r
516\r
517void show_iss (void)\r
518{\r
519 printf(" ");\r
520 info(12, "level", 'd');\r
521 putchar('\n');\r
522}\r
523\r
524void show_ils (void)\r
525{\r
526 printf(" ");\r
527 info( 2, "prec", 'b');\r
528 info( 5, "nint6", 'd');\r
529 info( 9, "ent", 'n');\r
530 info(11, NULL, 'x');\r
531 info(14, "nint", 'd');\r
532 info(15, "il1", 'd');\r
533 info(16, "il2", 'd');\r
534 putchar('\n');\r
535}\r
536\r
537void show_end (void)\r
538{\r
539 printf(" ");\r
540 info(0, "size", 'd');\r
541 info(3, "pta", 'x');\r
542 putchar('\n');\r
543}\r
544\r
545void show_endc(void)\r
546{\r
547 printf(" ");\r
548 info(52, "IX3", 'x');\r
549 info(53, "pta", 'x');\r
550 putchar('\n');\r
551}\r
552\r
553void show_81(void)\r
554{\r
555}\r
556\r
557void show_raw (char *name)\r
558{\r
559 int i;\r
560 printf("*%s", name);\r
561\r
562 for (i = 0; i < 12; i++)\r
563 printf(" %04x", buf[i]);\r
564\r
565 printf(" %s\n", getseq());\r
566}\r
567\r
568char * getseq (void)\r
569{\r
570 static char seq[10];\r
571 int i;\r
572\r
573 for (i = 0; i < 8; i++)\r
574 seq[i] = hollerith_to_ascii(card[72+i]);\r
575\r
576 seq[i] = '\0';\r
577 return seq;\r
578}\r
579\r
580\r
581void bail (char *msg)\r
582{\r
583 fprintf(stderr, "%s\n", msg);\r
584 exit(1);\r
585}\r
586\r
587void unpack (unsigned short *icard, unsigned short *obuf)\r
588{\r
589 int i, j;\r
590 unsigned short wd1, wd2, wd3, wd4;\r
591\r
592 for (i = j = 0; i < 54; i += 3, j += 4) {\r
593 wd1 = icard[j];\r
594 wd2 = icard[j+1];\r
595 wd3 = icard[j+2];\r
596 wd4 = icard[j+3];\r
597\r
598 obuf[i ] = (wd1 & 0xFFF0) | ((wd2 >> 12) & 0x000F);\r
599 obuf[i+1] = ((wd2 << 4) & 0xFF00) | ((wd3 >> 8) & 0x00FF);\r
600 obuf[i+2] = ((wd3 << 8) & 0xF000) | ((wd4 >> 4) & 0x0FFF);\r
601 }\r
602}\r
603\r
604void verify_checksum (unsigned short *obuf)\r
605{\r
606// unsigned short sum;\r
607\r
608 if (obuf[1] == 0) // no checksum\r
609 return;\r
610\r
611// if (sum != card[1])\r
612// printf("Checksum %04x doesn't match card %04x\n", sum, card[1]);\r
613}\r
614\r
615typedef struct {\r
616 unsigned short hollerith;\r
617 char ascii;\r
618} CPCODE;\r
619\r
620static CPCODE cardcode_029[] =\r
621{\r
622 0x0000, ' ',\r
623 0x8000, '&', // + in 026 Fortran\r
624 0x4000, '-',\r
625 0x2000, '0',\r
626 0x1000, '1',\r
627 0x0800, '2',\r
628 0x0400, '3',\r
629 0x0200, '4',\r
630 0x0100, '5',\r
631 0x0080, '6',\r
632 0x0040, '7',\r
633 0x0020, '8',\r
634 0x0010, '9',\r
635 0x9000, 'A',\r
636 0x8800, 'B',\r
637 0x8400, 'C',\r
638 0x8200, 'D',\r
639 0x8100, 'E',\r
640 0x8080, 'F',\r
641 0x8040, 'G',\r
642 0x8020, 'H',\r
643 0x8010, 'I',\r
644 0x5000, 'J',\r
645 0x4800, 'K',\r
646 0x4400, 'L',\r
647 0x4200, 'M',\r
648 0x4100, 'N',\r
649 0x4080, 'O',\r
650 0x4040, 'P',\r
651 0x4020, 'Q',\r
652 0x4010, 'R',\r
653 0x3000, '/',\r
654 0x2800, 'S',\r
655 0x2400, 'T',\r
656 0x2200, 'U',\r
657 0x2100, 'V',\r
658 0x2080, 'W',\r
659 0x2040, 'X',\r
660 0x2020, 'Y',\r
661 0x2010, 'Z',\r
662 0x0820, ':',\r
663 0x0420, '#', // = in 026 Fortran\r
664 0x0220, '@', // ' in 026 Fortran\r
665 0x0120, '\'',\r
666 0x00A0, '=',\r
667 0x0060, '"',\r
668 0x8820, 'c', // cent\r
669 0x8420, '.',\r
670 0x8220, '<', // ) in 026 Fortran\r
671 0x8120, '(',\r
672 0x80A0, '+',\r
673 0x8060, '|',\r
674 0x4820, '!',\r
675 0x4420, '$',\r
676 0x4220, '*',\r
677 0x4120, ')',\r
678 0x40A0, ';',\r
679 0x4060, 'n', // not\r
680 0x2820, 'x', // what?\r
681 0x2420, ',',\r
682 0x2220, '%', // ( in 026 Fortran\r
683 0x2120, '_',\r
684 0x20A0, '>',\r
685 0x2060, '>',\r
686};\r
687\r
688int hollerith_to_ascii (unsigned short h)\r
689{\r
690 int i;\r
691\r
692 h &= 0xFFF0;\r
693\r
694 for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++)\r
695 if (cardcode_029[i].hollerith == h)\r
696 return cardcode_029[i].ascii;\r
697\r
698 return '?';\r
699}\r
700\r
701// ---------------------------------------------------------------------------------\r
702// trim - remove trailing whitespace from string s\r
703// ---------------------------------------------------------------------------------\r
704\r
705void trim (char *s)\r
706{\r
707 char *nb;\r
708\r
709 for (nb = s-1; *s; s++)\r
710 if (*s > ' ')\r
711 nb = s;\r
712\r
713 nb[1] = '\0';\r
714}\r
715\r
716int ascii_to_ebcdic_table[128] = \r
717{\r
718 0x00,0x01,0x02,0x03,0x37,0x2d,0x2e,0x2f, 0x16,0x05,0x25,0x0b,0x0c,0x0d,0x0e,0x0f,\r
719 0x10,0x11,0x12,0x13,0x3c,0x3d,0x32,0x26, 0x18,0x19,0x3f,0x27,0x1c,0x1d,0x1e,0x1f,\r
720 0x40,0x5a,0x7f,0x7b,0x5b,0x6c,0x50,0x7d, 0x4d,0x5d,0x5c,0x4e,0x6b,0x60,0x4b,0x61,\r
721 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7, 0xf8,0xf9,0x7a,0x5e,0x4c,0x7e,0x6e,0x6f,\r
722\r
723 0x7c,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7, 0xc8,0xc9,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,\r
724 0xd7,0xd8,0xd9,0xe2,0xe3,0xe4,0xe5,0xe6, 0xe7,0xe8,0xe9,0xba,0xe0,0xbb,0xb0,0x6d,\r
725 0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87, 0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,\r
726 0x97,0x98,0x99,0xa2,0xa3,0xa4,0xa5,0xa6, 0xa7,0xa8,0xa9,0xc0,0x4f,0xd0,0xa1,0x07,\r
727};\r
728\r
729char *getname (unsigned short *ptr)\r
730{\r
731 static char str[6];\r
732 int i, j, ch;\r
733 long v;\r
734\r
735 v = (ptr[0] << 16L) | ptr[1];\r
736\r
737 for (i = 0; i < 5; i++) {\r
738 ch = ((v >> 24) & 0x3F) | 0xC0; // recover those lost two bits\r
739 v <<= 6;\r
740\r
741 str[i] = ' ';\r
742\r
743 for (j = 0; j < (sizeof(ascii_to_ebcdic_table)/sizeof(ascii_to_ebcdic_table[0])); j++) {\r
744 if (ascii_to_ebcdic_table[j] == ch) {\r
745 str[i] = j;\r
746 break;\r
747 }\r
748 }\r
749 }\r
750\r
751 str[5] = '\0';\r
752 return str;\r
753}\r
754\r
755\r