
/*
 * print a DOS-11 DECtape directory
 *
 */

#include <stdio.h>

unsigned char tape[576][512];
unsigned short uicblk[63][3];
char str[9];

/*                J   F   M   A   M   J   J   A   S   O   N   D            */
int monthLen[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

char *monthNam[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };

convdate( int date, char *str)
{
        int year;
        int month;
        int day;
        int i;
        int dayinyear;

	date &= 0xfff;

        year = (date / 1000) + 1970;
        dayinyear = (date % 1000);

        for (i=0; i<12; i++){
         month = i;
         if(dayinyear <= monthLen[i]){
          day = dayinyear;
          break;
         }
         else{
          dayinyear -=  monthLen[i];
          if(year != 2000){     
           if((i == 1)&&((year % 4) == 0)){     /* deal with Feb 29 */
            if( dayinyear == 1 ){
             day = 29;
             break;
            }
           }
          }
         }
        }

        sprintf(str, "%s %2d, %4d", monthNam[month], day, year);
}

/*
 * Convert Radix-50 integer to ASCII string.
 */

char atable[] = {
        ' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
        'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
        'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
        'X', 'Y', 'Z', '$', '.', '?', '0', '1',
        '2', '3', '4', '5', '6', '7', '8', '9'
};

r50toc (r50, str)
        unsigned int r50;
        char *str;
{
	r50 &= 0xffff;

        r50 = r50 & 65535;
        str[0] = atable[r50/03100L];
        r50 = r50%03100L;

        str[1] = atable[r50/050];
        str[2] = atable[r50%050];
        str[3] = '\0';
}

/*
 * UFD blocks:
 * +-------------------------------+
 * |      link to next UFD         |
 * +-------------------------------+
 * |      rad50 file name          | 28 file entries/blk
 * +-                             -+
 * |                               |
 * +-------------------------------+
 * |      rad50 file extn          |
 * +---+--------+------------------+
 * |C/L|        | 12 bit date      | year = date/1000+1970 day = remainder
 * +-------------------------------+
 * | next free byte                |
 * +-------------------------------+
 * | starting block                |
 * +-------------------------------+
 * | #blks in file                 |
 * +-------------------------------+
 * | last block                    |
 * +------+-------+----------------+
 * | lock | usage | protection byte|
 * +------+-------+----------------+
 *
 */

printUFD(unsigned char *p)
{
	unsigned char *blk;

	unsigned int i,n,j;
	unsigned int date, length, start, prot, nxtByte, lastBlk;

	p+=2;						// skip over link word

	for(n=0; n<28; n++){                            // 28 file names in the UFD
	 i = *p; i |= *(p+1)<<8;  p+=2;			// file name
	 if(i==0) continue;
	 r50toc (i, str); printf("%s", str);

	 i = *p; i |= *(p+1)<<8;  p+=2;
	 r50toc (i, str); printf("%s", str);

	 printf(".");		

	 i = *p; i |= *(p+1)<<8;  p+=2;
	 r50toc (i, str); printf("%s ", str);

	 date = *p; date |= *(p+1)<<8;  p+=2;
	 nxtByte = *p; nxtByte |= *(p+1)<<8;  p+=2;	// next byte
	 start = *p; start |= *(p+1)<<8;  p+=2;		// start blk
	 length= *p; length |= *(p+1)<<8;  p+=2;
	 lastBlk = *p; lastBlk |= *(p+1)<<8;  p+=2;	// last blk
	 prot = *p; prot |= *(p+1)<<8;  p+=2;

         printf("%5d",length);      			// #blks
	 if(date&0x8000)
	   putchar('C'); else putchar(' ');
	 convdate( date, str);
         printf(" %s ",str);      			// date
         printf("<%3o>",prot&0xff);			// prot

	 printf(" start:%4o last:%4o byte:%d\n", start, lastBlk, nxtByte);

	 blk = &tape[start][0];
	 i = start;
	 if(date&0x8000){				// Contiguous file
	 }
	 else{
	  j = 1;
#ifdef PRTBLKS
	  while(1){
		 printf("%4o ", i);
		 if(i == lastBlk) break;
		 if((j++%16)==0) printf("\n");
		 i = *blk; i |= *(blk+1)<<8;
		 blk = &tape[i][0];
	  }
#endif
	 }

//	 printf("\n"); fflush(stdout);
	 
	}
}

main(argc, argv)
int argc;
char **argv;
{
	unsigned char *p;
	unsigned int i, n, secondUFD;
	FILE *fp;
	
	if(!(fp  = fopen(argv[1],"rb"))) exit(1);
	if(fread(tape, 1, 294512, fp)!= 294512) exit(1);  	// image < 576 blks
	p = &tape[0100][0];  					// addr of mfd blk #1 (blk 0100)
	i = *p | *(p+1)<<8;
	if(i != 0101) {printf("Not a DOS-11 format DECtape\n"); exit(1);}
	p = &tape[i][0];     			// Adr of MFD blk #2 (should be 0101 == 0x41)
	p += 2;		     // link should be zero on dectapes
	// make list of UICs
	for(n=0; n<63; n++){
	 i = *p | *(p+1)<<8;
	 uicblk[n][0] = i;
	 p+=2;
	 i = *p | *(p+1)<<8;
	 uicblk[n][1] = i;
	 p+=2;
	 i = *p | *(p+1)<<8;
	 uicblk[n][2] = i;
	 p+=4;
	}
	// turns out on DECtape, multple MFD  entries point to the
	// two UFD blocks

	  p = &tape[0102][0];
	  printUFD(p);
	  i = *p | *(p+1) << 8;
	  p = &tape[i][0];   // pick up link word to second UFD
	  printUFD(p);
}
