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