/* DECtape image scanner (revised Nov 2004 for AA2 format) */ #include #include #define psym(f, k) fputc((k),f) static int *B; void shit (char *s, int n) {fprintf(stderr,"**SHIT(%o): %s\n",n,s);} void die (char *s, int n) {shit(s,n); exit(1);} int mangle (int n) { int i,m; n = ~n; m = (n&7)<<15; m += (n&070)<<9; m += (n&0700)<<3; m += (n&07000)>>3; m += (n&070000)>>9; return m+((n&0700000)>>15); } void mangleblock (int block) { int min,max,val; min = block*256; max = min+255; /*fprintf(stderr,"Mangling block %o %o:%o %o %o,",*/ /*block,min,max,B[min],B[max]);*/ while (min=0; i-=6) { j = (n>>i)&63; if (j) {if ((j&32)==0) j+=64; *s++ = j;} } #undef s } void aa1 (FILE *f, int n) { int i,j,k; for (i=12; i>=0; i-=6) { j = (n>>i)&63; if (j) { if ((j&32)==0) j+=64; if (j=='"') j = '\n'; if (j=='^') j = '@'; psym(f, j); } } } void dec1 (FILE *f, int n) { n = n&127; if (n=='\r') n = '\n'; if (n) psym(f, n); } void dec5 (FILE *f, int a, int b) { dec1(f, a>>11); dec1(f, a>>4); dec1(f, (a<<3)+((b>>15)&7)); dec1(f, b>>8); dec1(f, b>>1); } int bitmap (int fileno) { if (fileno<0) die("Fileno negative",fileno); if (fileno==0) return 256*64; if (fileno>56) die("Fileno excessive",fileno); return 256*57+((fileno-1)*32); } int blocksused (int bitmap) { int i,j,m,n; n=0; for (i=0; i<32; i++) { m = B[bitmap++]; j = 0400000; while (j) {if (m&j) n++; j >>= 1;} } return n; } int filedesc (int fileno) { if (fileno<1) die("Fileno too small",fileno); if (fileno>56) die ("Fileno too big",fileno); return 256*64+(fileno-1)*4+32; } char *printname (int d) { static char temp[256]; char *s = temp; sixbt(&s, B[d]); sixbt(&s, B[d+1]); *s++ = ' '; sixbt(&s, B[d+2]); *s = '\0'; return(strdup(temp)); } void dir (int *last) { int i,d,m,u; for (i=1; i<=24; i++) { d = filedesc(i); m = bitmap(i); u = blocksused(m); if (u || B[d+3]&0400000) { fprintf(stderr, "%02d %3d %s\n",i,u, printname(d)); } } *last = i; fprintf(stderr, "%11d\n",blocksused(0)); } void decfile (FILE *f, int start) { int p,lim,pairs,mangled=0,next; while (start>0) { /*fprintf(stderr,"//Next block %o\n",start);*/ p = start*256; lim = p+254; while (p>8,p&255,B[p]);*/ if (B[p]==0) break; if (B[p]==01005) break; if ((B[p]&0777)!=2) {shit("DEC format mode not 2",p); return;} pairs = B[p]>>9; p += 2; while(--pairs>0) { if (p>=lim) {shit("DEC record error",p-lim); return;} dec5(f, B[p],B[p+1]); p += 2; } } next = B[lim+1]; if (mangled) mangleblock(start); if (next=01100) start = -1; } } #define AA1 010161 #define AA2 010162 static int aa2last=1; void aa2one (FILE *f, int k) { if (k) { if (aa2last) {psym(f,k+31);} else if (k>32) {psym(f,k-32);} else psym(f,k+94); } aa2last = k; } void aa2three (FILE *f, int k) { aa2one(f,(k>>12)&63); aa2one(f,(k>>6)&63); aa2one(f,k&63); } void aa2file (FILE *f, int start) { int p,lim,sum=AA2,w,mangled=0,next; aa2last = 1; while (start>0) { p = start*256; lim = p+255; /*fprintf(stderr,"Block %o %o:%o %06o %06o sum %06o\n",*/ /*start,p,lim,B[p],B[lim],sum);*/ if (B[p++]!=(sum&0777777)) { shit("AA2 checksum error - remove -aa flag\?",p-1); return; } while (p=01100) start = -1; } } void aa1file (FILE *f, int start) { int p,lim,sum=AA1,w,mangled=0,next; while (start>0) { p = start*256; lim = p+255; /*fprintf(stderr,"Block %o %o:%o %06o %06o sum %06o\n",*/ /*start,p,lim,B[p],B[lim],sum);*/ if (B[p++]!=(sum&0777777)) { if (sum==AA1 && B[p-1]==AA2) {aa2file(f,start); return;} shit("AA1 checksum error - remove -aa flag\?",p-1); return; } while (p=01100) start = -1; } } int main(int argc, char **argv) { int aaflag = (0!=0); int size=576*256*4; int this, last, i; FILE *tape, *outfile; char dta[256], txt[256], *s; B = (int*) malloc(size); if (argc<2) die ("syntax: dectape [-aa] tapename",argc); if (strcmp(argv[1], "-aa") == 0) { aaflag = (0==0); argc -= 1; argv += 1; } mkdir(argv[1], 0777); sprintf(dta, "%s.dta", argv[1]); tape = fopen(dta,"rb"); if (tape==0) die("No tape file",0); i = fread(B,1,size,tape); fprintf(stderr, "Got %d out of %d bytes\n\n",i,size); fprintf(stderr, "Directory\n\n"); dir(&last); for (this = 1; this <= last; this++) { i = this; fprintf(stderr, "Going for file %d\n", i); i = filedesc(i); sprintf(txt, "%s/%s", argv[1], printname(i)); if ((s = strchr(txt, ' ')) != NULL) *s = '.'; s = txt + strlen(txt) - 1; if (*s == '.') *s = '\0'; s = txt; while (*s != '\0') { if (isalpha(*s) && isupper(*s)) *s = tolower(*s); s += 1; } fprintf(stderr, "That's file %s", txt); i = B[i+3]; fprintf(stderr, ", First block %o\n",i); i = i&01777; if (i) { outfile = fopen(txt, "wb"); if (aaflag) aa1file(outfile, i); else decfile(outfile, i); fclose(outfile); } } return(0); }