/* untap.c, J. Wilcoxson, March 19, 2005 Reads a tap magtape file and removes the tap information. tap reference: http://simh.trailing-edge.com/docs/simh_magtape.pdf NOTE: for this modified version, a 16-bit Prime word length is used to delimit records. */ #include #include #define BUFSIZE 16*1024 /* reads a 16-bit, big-endian record length, which is the number of 16-bit words in the tape record. The upper 3 bits are apparently flag bits, and these are moved the the upper 3 bits of the 32-bit word */ int readint_be () { int n,ch; n = (getchar()<<8 | getchar()); n = ((n & 0xE000) << 16) | ((n & 0x1FFF) * 2); if (feof(stdin)) { fprintf(stderr,"End of file reading record length, position = %d\n", ftell(stdin)); exit(0); } return n; } main (int argc, char** argv) { int fp; /* input file position, zero based */ int recno; /* record number, 1st record is 1 */ int reclen; /* length of record (bytes) */ int flag1,flag2; /* leading & trailing flags */ int i,ch; int ones; /* count of held-back "all ones" bytes */ int allff; /* true if record was all 1 bits */ int verbose; unsigned char buf[BUFSIZE]; unsigned char bufhdr[5]; /* hack to display Prime 4-char tape hdr */ /* init */ recno = 0; ones = 0; fp = 0; verbose = 0; /* check args */ for (i=1; i= 1) fprintf(stderr,"End of file at record %d\n", recno); exit(0); } fp=ftell(stdin); reclen = readint_be(); if (reclen == 0xFFFFFFFF) { /* end of medium */ if (verbose >= 1) fprintf(stderr,"End of medium at record %d, position %d\n", recno, fp); exit(0); } if (reclen == 0) { /* tape mark */ if (verbose >= 1) fprintf(stderr,"Tape mark at record %d, position %d\n", recno, fp); continue; } flag1 = reclen & 0xF0000000; if (flag1 != 0) fprintf(stderr,"Leading flags are 0x%08x, position %d\n", flag1, fp); reclen = reclen & 0x0FFFFFFF; if (reclen > BUFSIZE) { fprintf(stderr,"Record too big at record %d, position %d: increase BUFSIZE to %d\n", recno, fp, reclen); exit(1); } allff = 1; for (i=0; i= 2) { for (i=0; i<4; i++) bufhdr[i] = buf[i] & 0x7f; bufhdr[4] = 0; fprintf(stderr,"Record %d, position %d, length %d, hdr %s\n", recno, fp, reclen, bufhdr); } /* sometimes tap files end with a stream of 0xff bytes when there is no more data on the tape. To prevent writing this trailing stream of garbage, keep a count of records full of 0xff bytes and write them out when real data is seen again */ if (allff) { if (verbose >= 2) fprintf(stderr,"Record %d is all ones, position %d\n", recno, fp); ones += reclen; } else { while (ones-- > 0) putchar(0xff); ones = 0; for (i=0; i