int Drive;
int numsecs;
int numtracks;
int numheads;
unsigned char *SectorBuffer;
unsigned short *TrackBuffer,*CheckBuffer,*WriteBuffer;

main(argc,argv)
int argc;
char **argv;
{
int List[30];
int drive,track,head;
char c;
int Error,i;

drive=0;
numsecs=10;
numtracks=80;
numheads=2;

while (argc-->1) 
{i=atoi(argv[argc]);
 if (i<4) drive=i;
 else if (i<12) numsecs=i;
 else numtracks=i;}

printf("WARNING!!! This program will format the disk in drive %d, Format:\n		%d sectors/Track,%d tracks/disk, %d Heads - MSDOS\n",drive,numsecs,numtracks,numheads);
printf("IS THIS WHAT YOU REALLY WANT TO DO????\n");
scanf("%c",&c);
if (toupper(c)!='Y') {printf("Poooh... Finishing.\n");_abort();}

/* Do the Initialization stuff */
Drive=drive;
InitMotor();
TrackBuffer=(unsigned short *)AllocChipMem(2*TrackLen);
CheckBuffer=(unsigned short *)AllocChipMem(2*TrackLen);
WriteBuffer=(unsigned short *)AllocChipMem(2*TrackLen);
SectorBuffer=(unsigned char *)AllocNormalMem(512);

/* First, Create an Empty Track */
CreateEmptyStandardTrack(TrackBuffer,0,0,numsecs);
CreateList(TrackBuffer,List);
for (track=0;track<numtracks;track++)
 for (head=0;head<numheads;head++)
  {
  /* Now adjust the TrackMarks */
  ChangeStandardTrack(TrackBuffer,track,head,numsecs);

  again:
  Chk_Abort();
  for (i=0;i<4;i++)
  {

  /* Now Write the Track to Disk */
  Error=WriteTrack(TrackBuffer,drive,track,head);

  /* And now check the result (obsolete with good disks) */
  if (Error==0) Error=CheckTrackList(TrackBuffer,drive,track,head,List,CheckBuffer);

  if (Error==0) break;
  printf("Retrying Track %d...\n",track);
  }
  /* Errors have occured-Request abort */
  if (Error) {aprintf(stderr,"Error writing track %d.\n",track);goto again;}
  }
/* Done with this disk - Now write the Format-Sectors and Bytes */
  WriteMsFormat();
_abort();
}

WriteMsFormat()
{
 int List[30];
 int WrList[30];
 int FormatByte;
 int lenfat;
 int drive=Drive;
 int blocknum;

 onceagain:
 CreateStandardBootSector(SectorBuffer,numtracks,numheads,numsecs);

 /* Calculate Formats for non-3.2 Disks */
 FormatByte=0xff;
 if ((numtracks==80)&&(numsecs==9)&&(numheads==2))
  {
   FormatByte=0xf9;
   SectorBuffer[21]=FormatByte;

   /* The Specifications for 3.3 are not precise
      Use one of the following, just as your DOS prefers:
   SectorBuffer[22]=5; 5 Sektoren fuer FAT
   SectorBuffer[13]=1; 1 Sektor pro Cluster
   SectorBuffer[17]=0xe0; Oder vielleicht 0xe0 Directoryeintraege?
     PCDOS 3.3 versteht diesen: */
   SectorBuffer[22]=2; /* 2 Sektoren fuer FAT */
  }
 if ((numtracks==40)&&(numsecs==9)&&(numheads==2))
  {
   FormatByte=0xfd;
   SectorBuffer[21]=FormatByte;
   SectorBuffer[22]=2; /* 2 Sektoren fuer die FAT */
  }
 if (FormatByte==0xff)
  {
  /* No Standard-MSDOS-Format! */;
  FormatByte=SectorBuffer[21];
  }

 /* Now, read in the very first track and prepare it for writing back */
 if (ReadTrackList(TrackBuffer,drive,0,0,List)) goto failure;
 CreateStandardTrack(WriteBuffer,numsecs);
 if(CopyList(WriteBuffer,TrackBuffer,numsecs,WrList,List)) goto failure;

 /* Now, write the BootBlock into the first Sector */
 if (WriteList(WriteBuffer,SectorBuffer,1,WrList)) goto failure;

 /*Now, write the FormatBytes to the FATs, assuming they both reside in Track 1*/

 lenfat=SectorBuffer[22];
 blocknum=SectorBuffer[14];
 if (ReadList(WriteBuffer,SectorBuffer,blocknum+1,WrList)) goto failure;
 SectorBuffer[0]=FormatByte;
 SectorBuffer[1]=0xff;
 SectorBuffer[2]=0xff;
 if (WriteList(WriteBuffer,SectorBuffer,blocknum+1,WrList)) goto failure;

 blocknum+=lenfat;
 if (ReadList(WriteBuffer,SectorBuffer,blocknum+1,WrList)) goto failure;
 SectorBuffer[0]=FormatByte;
 SectorBuffer[1]=0xff;
 SectorBuffer[2]=0xff;
 if (WriteList(WriteBuffer,SectorBuffer,blocknum+1,WrList)) goto failure;

 /*TATA-We're done, Write the Track to Disk and say OK! */
 if (WriteTrack(WriteBuffer,drive,0,0)) goto failure;

return(0);
failure:
 aprintf(stderr,"Error writing Diskinfos!!");
 goto onceagain;
}


CheckTrackList(TrackBuffer,drive,track,head,List,CheckBuffer)
int drive,track,head;
unsigned short *TrackBuffer,*CheckBuffer;
int *List;
{
 int Error,i,k;
 int CheckList[30];
 long *old,*new;

 /* Read in the whole Track first */
 if (ReadTrackList(CheckBuffer,drive,track,head,CheckList)) return(-1);
 /* For all Sectors that existed in the old Track: */
 for (i=2;List[i]!=0;i+=2)
 	{
	 /* Are the old Sectors present in the new Track?*/
	 if ((CheckList[i]==0)||(CheckList[i+1]==0)) return(-1);
	 /* Yes, So check the AddressSpace first: */
	 old=(long *) (TrackBuffer+List[i]);
	 new=(long *) (CheckBuffer+CheckList[i]);
	 for (k=0;k<3;k++)
	 	if (*old++!=*new++)
		 {
		  return(-1);
		 }
 	 if (*(short *)old!=*(short *)new)
	  {
	   return(-1);
	  }
	 /* And now, check the DataSpace: */
	 old=(long *) (TrackBuffer+List[i+1]);
	 new=(long *) (CheckBuffer+CheckList[i+1]);
	 for (k=0;k<258;k++)
	 	if (*old++!=*new++)
		 {
		  return(-1);
		 }
	}
 return(0);
}
