#include <stdio.h>
#include <string.h>

typedef unsigned char BYTE;


void main(int argc, char * argv[])
{
   FILE * fp;
   FILE * Outfile;
   long DirectoryStart = 0xB400;
   BYTE tmp1,tmp2;
   long ExtractStart = 0;
   BYTE Buffer[128];
   int NextSecNum;
   int Loops = 0;
   int Len;
   
   if ((argc < 2) || (argc > 3))
   {
      printf("ADIR 1.1 shows directory listings of .XFD and .ATR ");
      printf("Atari disk images.\nAn attempt will be made to extract ");
      printf("an Atari filename if one is specified.\n");
      printf("Comments to ivan@rcp.co.uk\n\n");
      printf("Usage: ADIR <filename.xfd/atr> [extract filename]\n");
      return;
   }

   fp = fopen(argv[1], "rb");
   if (fp == NULL)
   {
      printf("Disk image file not found\n");
      return;
   }

   /* check for an ATR file header */
   tmp1 = (BYTE)fgetc(fp);
   tmp2 = (BYTE)fgetc(fp);
   if (tmp1 == 0x96 && tmp2 == 2)
      DirectoryStart = 0xB410;
   
   fseek(fp, DirectoryStart, SEEK_SET);

   if (argc == 2)
      printf("Start Sec  Num Sectors  Filename\n");
   
   while(1)
   {
      BYTE Low, Hi, Attr;
      int Start, i, x;
      char Name[13];
      
      Attr = (BYTE)fgetc(fp);
      if (Attr == 0)
	 break;

      Low = (BYTE)fgetc(fp);
      Hi = (BYTE)fgetc(fp);

      Len = 256 * Hi + Low;

      Low = (BYTE)fgetc(fp);
      Hi = (BYTE)fgetc(fp);
      
      Start = 256 * Hi + Low;

      for (i = 0; i < 8; i ++)
	 Name[i] = (char)fgetc(fp);

      for (i = 7; i > 0; i --)
	 if (Name[i] != ' ')
	    break;

      Name[++i] = '.';

      for (x = 0; x < 3; x ++)
	 Name[++i] = (char)fgetc(fp);

      for (x = i; x > 0; x --)
      {
	 if ((Name[x] != ' ') && (Name[x] != '.'))
	       break;
      }
      
      Name[++x] =  '\0';
      
      if (argc == 2)
      {
	 /* just displaying */
	 printf("  %04X         %04X     %s", Start, Len, Name);
	 
	 if ((Attr & 0x80) == 0x80)
	    printf(" (deleted)\n");
	 else
	    printf("\n");
      }
      else
      {
	 /* extracting - can't extract deleted file */
	 if ((_strnicmp(Name, argv[2], x) == 0) && ((Attr & 0x80) != 0x80))
	 {
	    printf("Start Sec  Num Sectors  Filename\n");
	    printf("  %04X         %04X     %s\n", Start, Len, Name);
	    ExtractStart = ((long)Start * 128) - 128;
	    break;
	 }
      }
   }

   /* if we are not extracting end */
   if (argc == 2)
   {
      fcloseall();
      return;
   }
   
   if (ExtractStart == 0)
   {
      printf("Can't find file to extract\n");
      fcloseall();
      return;
   }

   Outfile = fopen(argv[2], "wb");
   if (Outfile == NULL)
   {
      printf("Can't create %s\n", argv[2]);
      fcloseall();
      return;
   }

   while (1)
   {
      /* Add header for .ATR files */
      if (DirectoryStart == 0xB410)
	 ExtractStart+= 0x10;
      
      fseek(fp, ExtractStart, SEEK_SET);

      /* read one sector */
      fread(Buffer, 128, 1, fp);

      fwrite(Buffer, (size_t)Buffer[127], 1, Outfile);

      Loops ++;

      /* finished */
      if (Loops == Len)
	 break;

      
      /* calc next sector */
      NextSecNum = (((int)Buffer[125] & 3) * 256) + (int)Buffer[126];
      ExtractStart = ((long)NextSecNum * 128) - 128;

   }
   
   fcloseall();
}
