| /* Simple program to display a binary card-image file in ASCII. | |
| * We assume the deck was written with one card per 16-bit word, left-justified, | |
| * and written in PC little-endian order | |
| * | |
| * (C) Copyright 2002, Brian Knittel. | |
| * You may freely use this program, but: it offered strictly on an AS-IS, AT YOUR OWN | |
| * RISK basis, there is no warranty of fitness for any purpose, and the rest of the | |
| * usual yada-yada. Please keep this notice and the copyright in any distributions | |
| * or modifications. | |
| * | |
| * This is not a supported product, but I welcome bug reports and fixes. | |
| * Mail to sim@ibm1130.org | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include "util_io.h" | |
| #define TRUE 1 | |
| #define FALSE 0 | |
| typedef int BOOL; | |
| int hollerith_to_ascii (unsigned short h); | |
| void bail (char *msg); | |
| void format_coldstart (unsigned short *buf); | |
| int main (int argc, char **argv) | |
| { | |
| FILE *fd; | |
| char *fname = NULL, line[82], *arg; | |
| BOOL coldstart = FALSE; | |
| unsigned short buf[80]; | |
| int i, lastnb; | |
| static char usestr[] = | |
| "Usage: viewdeck [-c] deckfile\n" | |
| "\n" | |
| "-c: convert cold start card to 16-bit format as a C array initializer\n"; | |
| for (i = 1; i < argc; i++) { // process command line arguments | |
| arg = argv[i]; | |
| if (*arg == '-') { | |
| arg++; | |
| while (*arg) { | |
| switch (*arg++) { | |
| case 'c': | |
| coldstart = TRUE; | |
| break; | |
| default: | |
| bail(usestr); | |
| } | |
| } | |
| } | |
| else if (fname == NULL) // first non-switch arg is file name | |
| fname = arg; | |
| else | |
| bail(usestr); // there can be only one name | |
| } | |
| if (fname == NULL) // there must be a name | |
| bail(usestr); | |
| if ((fd = fopen(fname, "rb")) == NULL) { | |
| perror(fname); | |
| return 1; | |
| } | |
| while (fxread(buf, sizeof(short), 80, fd) == 80) { | |
| if (coldstart) { | |
| format_coldstart(buf); | |
| break; | |
| } | |
| lastnb = -1; | |
| for (i = 0; i < 80; i++) { | |
| line[i] = hollerith_to_ascii(buf[i]); | |
| if (line[i] > ' ') | |
| lastnb = i; | |
| } | |
| line[++lastnb] = '\n'; | |
| line[++lastnb] = '\0'; | |
| fputs(line, stdout); | |
| } | |
| if (coldstart) { | |
| if (fxread(buf, sizeof(short), 1, fd) == 1) | |
| bail("Coldstart deck has more than one card"); | |
| } | |
| fclose(fd); | |
| return 0; | |
| } | |
| void format_coldstart (unsigned short *buf) | |
| { | |
| int i, nout = 0; | |
| unsigned short word; | |
| for (i = 0; i < 80; i++) { | |
| word = buf[i]; // expand 12-bit card data to 16-bit instruction | |
| word = (word & 0xF800) | ((word & 0x0400) ? 0x00C0 : 0x0000) | ((word & 0x03F0) >> 4); | |
| if (nout >= 8) { | |
| fputs(",\n", stdout); | |
| nout = 0; | |
| } | |
| else if (i > 0) | |
| fputs(", ", stdout); | |
| printf("0x%04x", word); | |
| nout++; | |
| } | |
| putchar('\n'); | |
| } | |
| typedef struct { | |
| unsigned short hollerith; | |
| char ascii; | |
| } CPCODE; | |
| static CPCODE cardcode_029[] = | |
| { | |
| 0x0000, ' ', | |
| 0x8000, '&', // + in 026 Fortran | |
| 0x4000, '-', | |
| 0x2000, '0', | |
| 0x1000, '1', | |
| 0x0800, '2', | |
| 0x0400, '3', | |
| 0x0200, '4', | |
| 0x0100, '5', | |
| 0x0080, '6', | |
| 0x0040, '7', | |
| 0x0020, '8', | |
| 0x0010, '9', | |
| 0x9000, 'A', | |
| 0x8800, 'B', | |
| 0x8400, 'C', | |
| 0x8200, 'D', | |
| 0x8100, 'E', | |
| 0x8080, 'F', | |
| 0x8040, 'G', | |
| 0x8020, 'H', | |
| 0x8010, 'I', | |
| 0x5000, 'J', | |
| 0x4800, 'K', | |
| 0x4400, 'L', | |
| 0x4200, 'M', | |
| 0x4100, 'N', | |
| 0x4080, 'O', | |
| 0x4040, 'P', | |
| 0x4020, 'Q', | |
| 0x4010, 'R', | |
| 0x3000, '/', | |
| 0x2800, 'S', | |
| 0x2400, 'T', | |
| 0x2200, 'U', | |
| 0x2100, 'V', | |
| 0x2080, 'W', | |
| 0x2040, 'X', | |
| 0x2020, 'Y', | |
| 0x2010, 'Z', | |
| 0x0820, ':', | |
| 0x0420, '#', // = in 026 Fortran | |
| 0x0220, '@', // ' in 026 Fortran | |
| 0x0120, '\'', | |
| 0x00A0, '=', | |
| 0x0060, '"', | |
| 0x8820, '\xA2', // cent, in MS-DOS encoding | |
| 0x8420, '.', | |
| 0x8220, '<', // ) in 026 Fortran | |
| 0x8120, '(', | |
| 0x80A0, '+', | |
| 0x8060, '|', | |
| 0x4820, '!', | |
| 0x4420, '$', | |
| 0x4220, '*', | |
| 0x4120, ')', | |
| 0x40A0, ';', | |
| 0x4060, '\xAC', // not, in MS-DOS encoding | |
| 0x2420, ',', | |
| 0x2220, '%', // ( in 026 Fortran | |
| 0x2120, '_', | |
| 0x20A0, '>', | |
| 0xB000, 'a', | |
| 0xA800, 'b', | |
| 0xA400, 'c', | |
| 0xA200, 'd', | |
| 0xA100, 'e', | |
| 0xA080, 'f', | |
| 0xA040, 'g', | |
| 0xA020, 'h', | |
| 0xA010, 'i', | |
| 0xD000, 'j', | |
| 0xC800, 'k', | |
| 0xC400, 'l', | |
| 0xC200, 'm', | |
| 0xC100, 'n', | |
| 0xC080, 'o', | |
| 0xC040, 'p', | |
| 0xC020, 'q', | |
| 0xC010, 'r', | |
| 0x6800, 's', | |
| 0x6400, 't', | |
| 0x6200, 'u', | |
| 0x6100, 'v', | |
| 0x6080, 'w', | |
| 0x6040, 'x', | |
| 0x6020, 'y', | |
| 0x6010, 'z', // these odd punch codes are used by APL: | |
| 0x1010, '\001', // no corresponding ASCII using ^A | |
| 0x0810, '\002', // SYN using ^B | |
| 0x0410, '\003', // no corresponding ASCII using ^C | |
| 0x0210, '\004', // PUNCH ON using ^D | |
| 0x0110, '\005', // READER STOP using ^E | |
| 0x0090, '\006', // UPPER CASE using ^F | |
| 0x0050, '\013', // EOT using ^K | |
| 0x0030, '\016', // no corresponding ASCII using ^N | |
| 0x1030, '\017', // no corresponding ASCII using ^O | |
| 0x0830, '\020', // no corresponding ASCII using ^P | |
| }; | |
| int hollerith_to_ascii (unsigned short h) | |
| { | |
| int i; | |
| h &= 0xFFF0; | |
| for (i = 0; i < sizeof(cardcode_029) / sizeof(CPCODE); i++) | |
| if (cardcode_029[i].hollerith == h) | |
| return cardcode_029[i].ascii; | |
| return '?'; | |
| } | |
| void bail (char *msg) | |
| { | |
| fprintf(stderr, "%s\n", msg); | |
| exit(1); | |
| } | |