/* 4.3. 1989 FCopy.c   © by Heiner Hückstädt */
#include "fgadgets.h"

extern struct IOStdReq *TDOpen();
extern TDClose();
extern UBYTE blockmerker[1760];
extern ULONG *bitbuffer;

char copyright1[] = 
"FCOPY AMIGA V.1.2";

BYTE copyright2[] = 
{0x57,0x53,0x4b,0x57,0x50,0x40,0x48,0x27,0x39,0x30,0x32,0x33,0x23,0x35,0x37,
0x2f,0x52,0x48,0x32,0x5b,0x3a,0x35,0x5e,0xcb,0x5b,0x52,0x49,0x4f,0xd8,
0x59,0x4a,0x00};
/* char copyright2[] = 
"WRITTEN 1988/89 BY H. HÜCKSTÄDT"; */

char info[] = 
"SEE DOC.FILE FOR FURTHER INFORMATION";
char title[] = 
"FCOPY AMIGA V.1.2  1988/1989                                                ";
struct NewScreen CopyScreen =
{0,0,640,256,2,0,0,HIRES|SPRITES,CUSTOMSCREEN,0,0,0};
struct Screen *screen;

struct NewWindow CopyWindow =
{0,0,640,256,0,0,0,NOCAREREFRESH|ACTIVATE|BORDERLESS,
0,0,0,0,0,0,0,0,0,CUSTOMSCREEN};
struct Window *window;

USHORT colors[4] = {0x000,0x009,0xf00,0xfff};

#define TRACKSPRITE_HEIGHT 17
USHORT TrackSprite_dat[]=  {
     /*plane1  plane0 */
      0x0000,  0x0000,
      0x0000,  0xffc0,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0xa140,  0x6180,
      0x0000,  0xffc0,
      0x0000,  0x0000
     };
struct SimpleSprite TrackSprite =
     { 0,TRACKSPRITE_HEIGHT,0,10,6 };
ULONG spritenr;

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct RastPort *rp;
struct ViewPort *vp;
UBYTE *bitmapbuffer; ULONG bitblock;
USHORT *spritebuffer;
ULONG *writebuffer,*verifybuffer;
UBYTE trackbuffer[80];
ULONG trackpos[80];ULONG blockpos[22];
BOOL ramthere = FALSE;
struct IOStdReq *g_diskreq[5];

char *port[] = {"df0.port","df1.port","df2.port","df3.port","rad.port"};
char *device[] = {"trackdisk.device","ramdrive.device"};
char *drives[] = {"DF0","DF1","DF2","DF3","RAD"};
char really[] = "     REALLY ??     ";
char error[]  = "   FATAL ERROR !   ";
char newdiskname[] = "NEW DISK NAME";
char ret[] = "RETURN";
char esc[] = "ESCAPE";
char on[] = "ON ";
char off[] = "OFF";
char bam[]   = "BAM  ";
char track[] = "TRACK";
char initialize[] = "INSERT DISK TO INITIALIZE IN SOURCE DRIVE";
char examine[] =
"INSERT DISK TO EXAMINE IN SOURCE DRIVE";
char copyerror1[] =
"SOURCE & DESTINATION WITH THE SAME DRIVE. I'LL NEVER DO THAT !";
char copy[] =
"INSERT DISKS TO COPY IN DRIVES";
char readmap[] = "READING BITMAP";
char bitmaperr[] = "ERROR READING BITMAP";
char dnv[] = "SOURCE DISK NOT VALIDATED";
char *optim[] = {"OFF","ONE","TWO"};
UBYTE verify = 0;        /* 1 - ON     0 - OFF */
BOOL form   = TRUE;      /* TRUE - Formatieren  FALSE nicht */
BOOL copymode = TRUE;    /* TRUE - BAM    FALSE - TRACK */
BOOL fastmode = FALSE;   /* TRUE - ON     FALSE - OFF */
UBYTE optimizer = 0;     /* 2 = fastdir 1 = fastload 0 = OFF */
ULONG anzahldrives;

DisplaySprite()
      {
         spritenr = GetSprite(&TrackSprite,6L);
      }
box (x,y,x1,y1,farbe)
register long x,y,x1,y1,farbe;
      {
      SetAPen(rp,farbe);
      MOVE(rp,x,y);
      Draw(rp,x1,y);
      Draw(rp,x1,y1);
      Draw(rp,x,y1);
      Draw(rp,x,y);
      }
print (text,x,y,farbe)
register UBYTE *text;
register long x,y,farbe;
      {
      SetAPen(rp,farbe);
      MOVE(rp,x,y);
      Text(rp,text,(long)strlen(text));
      }
printbox (text,farbe)
register UBYTE *text;
register long farbe;
      {
      register long len,xpos;

      len = TextLength(rp,text,(long)strlen(text));
      xpos = 320L-(len/2);
      WaitTOF();
      ClearSmallDisplay();
      SETDRMD(rp,JAM1); 
      print(text,xpos,SMALLY,0L);
      print(text,xpos+1L,SMALLY,farbe);
      SETDRMD(rp,JAM2); 
      }
Copper()
{
register struct UCopList *CopperList;
register long i;
register long delay = 0x1L;
register long farbe = 0x0L;

CopperList = AllocMem((long)sizeof(struct UCopList),MEMF_CHIP|MEMF_CLEAR);

 CWAIT(CopperList,0L,30L); 
 CMOVE(CopperList,custom.color[29],0xff0L);
 CMOVE(CopperList,custom.color[30],0xaa0L);
 CMOVE(CopperList,custom.color[31],0x440L); 
 for(i=1;i<256;i++)
   {
    CWAIT(CopperList,i,30L);
    CMOVE(CopperList,custom.color[3],0xfff-(farbe*0x111));
    CMOVE(CopperList,custom.color[1],0x009+(farbe*0x1));
    CMOVE(CopperList,custom.color[2],0xf33+(farbe*0x11)); 
    farbe += delay;
      if(farbe > 0x6) {delay = -0x1;farbe += delay;}
      if(farbe < 0x0) {delay =  0x1;farbe += delay;}
   }
 CEND(CopperList);
 vp->UCopIns = CopperList; /* Pointer verbiegen */

 RethinkDisplay();
}
IDCMPOff()
      {
      ModifyIDCMP(window,0L);
      }
IDCMPOn()
      {
      ModifyIDCMP(window,RAWKEY|GADGETDOWN);
      }
BoxGadgets(first,xoffset,yoffset,color)
register struct Gadget *first;
register long xoffset,yoffset;
register long color;
 {
  register long x,y,x1,y1;

  while(first)
     {
      x = xoffset-1L+(long)(first->LeftEdge);
      y = yoffset-1L+(long)(first->TopEdge);
      x1 = x+1L+(long)(first->Width);
      y1 = y+1L+(long)(first->Height);
      box(x,y,x1,y1,color);
      first = (struct Gadget *)first->NextGadget;
     } 
 }
JaNein(schrift)
register char *schrift;
 {
  register ULONG class;
  register USHORT code,backcode;
  register BOOL Ende = FALSE;
  register struct IntuiMessage *message;

   Request(&janeinreq,window);
   SETDRMD(rp,JAM1);
   print(schrift,244L,120L,0L);
   print(schrift,245L,120L,1L);
   print(&ret[0],231L,137L,0L);
   print(&esc[0],361L,137L,0L);
   SETDRMD(rp,JAM2);
   box(220L,100L,420L,150L,2L);
   box(221L,101L,419L,149L,0L);
   BoxGadgets(&escapegad,220L,100L,2L);
   IDCMPOn();
   while(!Ende)
     {
        if(key()==0x75){backcode = ESC;Ende = TRUE;}
        if(key()==0x77){backcode = RETURN;Ende = TRUE;}
         while(message = (struct IntuiMessage *)GetMsg(window->UserPort))
            {
            class = message->Class;
            ReplyMsg(message);
            switch (class)
              {
               case GADGETDOWN:
                    code = message->IAddress->GadgetID;
                    switch (code)
                       {
                       case ESC:
                         backcode = ESC;
                         Ende = TRUE;
                       break;
                       case RETURN:
                         backcode = RETURN;
                         Ende = TRUE;
                       break;
                      }
              }
            }
     }
EndRequest(&janeinreq,window);
return (backcode);
}

HauptSchleife()
 {
  register ULONG class;
  register USHORT code;
  register ULONG s = 0;
  register ULONG d = 1;
  register BOOL Ende = FALSE;
  register struct IntuiMessage *message;

   IDCMPOn();
   while(!Ende)

     {
      Wait (1L << window->UserPort->mp_SigBit);
        while(message = (struct IntuiMessage *)GetMsg(window->UserPort))
            {
            class = message->Class;
            code  = message->Code;
  /*        printf("%x\n",code);  */
            ReplyMsg(message);

            switch (class)
              {
               case GADGETDOWN:
                    code = message->IAddress->GadgetID;
                    goto switchme;
               case RAWKEY:
switchme:
                    switch (code)
                       {
                       case QUIT:
                         Ende = TRUE;
                       break;
                       case SOURCE:
                         s++;
                         if(s>anzahldrives) s=0;
                         print(drives[s],168L,214L,3L);
                         print(drives[s],607L,222L,3L);
                         print(drives[s],392L,238L,3L);
                       break;
                       case DESTINATION:
                         d++;
                         if (d>anzahldrives) d=0;
                         print(drives[d],168L,222L,3L);
                       break;
                       case COPYMODE:
                         if (copymode)
                              {
                               copymode = FALSE;
                               print(&track[0],168L,230L,3L);
                              }
                         else
                              {
                               copymode = TRUE;
                               print(&bam[0],168L,230L,3L);
                              }
                       break;
                       case FORMAT:
                         if (form)
                              {
                               form = FALSE;
                               print(&off[0],607L,238L,3L);
                              }
                         else
                              {
                               form = TRUE;
                               print(&on[0],607L,238L,3L);
                              }
                       break;
                         case TURBOMODE:
                         if (fastmode)
                              {
                               fastmode = FALSE;
                               print(&off[0],168L,238L,3L);
                              }
                         else
                              {
                               fastmode = TRUE;
                               print(&on[0],168L,238L,3L);
                              }
                       break;
                       case VERIFY:
                         if (verify)
                              {
                               verify = 0;
                               print(&off[0],607L,214L,3L);
                              }
                         else
                              {
                               verify = 1;
                               print(&on[0],607L,214L,3L);
                              }
                       break;
                       case EXAMINE:
                         printbox(&examine[0],1L);
                         if (JaNein(&really[0]) == RETURN){
                                                 ExamineDisk(s);
                                                 DisplayBeep(screen);
                                                }
                         ClearSmallDisplay();
                       break;

                       case OPTIMIZER:
                              optimizer++;
                              if (optimizer > 2) optimizer = 0;
                              print(optim[optimizer],607L,230L,3L);
                       break;

    		       case INITIALIZE:
                              printbox(&initialize[0],1L);
                              Initialize(s);
 			      DisplayBeep(screen);
                              ClearSmallDisplay();
                       break;

    		       case ABOUT:
                              ProgramInfo();
                       break;
                       case GO:
                         if (s != d)
                             {
                              printbox(&copy[0],1L);
                              if(JaNein(&really[0]) == RETURN)
                                         {
                                          Copy(s,d);
                                          DisplayBeep(screen);
                                         }
                             }
                         else
                             {
                              printbox(&copyerror1[0],1L);
                              JaNein(&error[0]);
                             }
                         ClearSmallDisplay();
                       break;
                       }

              }
            }
     }
}
Zeichne()
  {
   print("00000000001111111111222222222233333333334444444444555555555566666666667777777777"
   ,0L,17L,3L);
   print("01234567890123456789012345678901234567890123456789012345678901234567890123456789"
   ,0L,25L,1L);

   SETDRMD(rp,JAM1);
   print(&title[0],0L,7L,3L);print(&title[0],0L,8L,2L);
   SETDRMD(rp,JAM2);
   
   print("Q",320L,8L,3L);print("UIT ME",328L,8L,2L);
   box (318L,0L,377L,10L,1L);
   box (0L,206L,639L,255L,3L);
   ClearSmallDisplay();
   box (1L,240L,638L,254L,2L);
      
   print("S                   DF0",8L,214L,3L);   
    print("ource      Drive :",16L,214L,2L);
   print("D                   DF1",8L,222L,3L);
    print("estination Drive :",16L,222L,2L);
   print("C                   BAM",8L,230L,3L);
    print("opy Mode         :",16L,230L,2L);
   print("T                   OFF",8L,238L,3L);
    print("urbo Mode        :",16L,238L,2L);
   print("V                   OFF",447L,214L,3L);
    print("erify            :",455L,214L,2L);
   print("E                   DF0",447L,222L,3L);
    print("xamine Disk      :",455L,222L,2L);
   print("O                   OFF",447L,230L,3L);
    print("ptimizer         :",455L,230L,2L);
   print("F                   ON",447L,238L,3L);
    print("ormat            :",455L,238L,2L);
   print("===>  o",232L,214L,2L);print("G",272L,214L,3L);
   print("A",232L,230L,3L);
    print("bout FCOPY",240L,230L,2L);
   print("I                   DF0",232L,238L,3L);
    print("nitialize Drive  :",240L,238L,2L);
  }
ProgramInfo()
{
     register ULONG class;
     register USHORT code;
     register BOOL Ende = FALSE;
     register struct IntuiMessage *message;

     Request(&inforeq,window);
     SETDRMD(rp,JAM1);
     print(&ret[0],412L,138L,2L);
     print(&copyright1[0],252L,75L,0L);
     print(&copyright1[0],253L,75L,3L);
     print(&copyright2[0],196L,90L,0L);
     print(&copyright2[0],197L,90L,3L);
     print(&info[0],176L,105L,0L);
     print(&info[0],177L,105L,3L);
     SETDRMD(rp,JAM2);
     box(160L,50L,480L,150L,1L);
     box(161L,51L,479L,149L,3L);
     box(162L,52L,478L,148L,0L);
     BoxGadgets(&infogad,160L,50L,0L);

    while(!Ende)
     {
        if(key()==0x77) Ende = TRUE;
         while(message = (struct IntuiMessage *)GetMsg(window->UserPort))
            {
            class = message->Class;
            ReplyMsg(message);
            switch (class)
              {
               case GADGETDOWN:
                    code = message->IAddress->GadgetID;
                    if(code == RETURN) Ende = TRUE;
              }
            }
    } 
  EndRequest(&inforeq,window);
} 
ClearSmallDisplay()
  {
   SetAPen(rp,3L);
   RectFill(rp,2L,241L,637L,253L);
  }
ClearBigDisplay()
  {
   SetAPen(rp,0L);
   RectFill(rp,0L,27L,639L,205L);
  }
Fastmode(schalter)
register int schalter;
  {
   if(schalter)
      {
      OFF_DISPLAY;
      }
   else
      {
      ON_DISPLAY;
      }

}
ForbidDrive(unit,flag)
register LONG unit,flag;
     {
     static BYTE *DriveName[NUMUNITS] = {"DF0:","DF1:","DF2:","DF3:"};
     struct MsgPort *device, *reply;
     register struct StandardPacket *packet;
     register LONG result = DOSFALSE;
     if((device = DeviceProc(DriveName[unit])))
        {
         if((reply = CreatePort(0L,0L)))
            {
             if((packet = (struct StandardPacket *)
                 AllocMem((ULONG)sizeof(struct StandardPacket),
                           (ULONG)MEMF_PUBLIC|MEMF_CLEAR)) !=NULL)
               {
                packet->sp_Msg.mn_Node.ln_Name = (char *)&packet->sp_Pkt;
                packet->sp_Pkt.dp_Link = &packet->sp_Msg;
                packet->sp_Pkt.dp_Port = reply;
                packet->sp_Pkt.dp_Type = ACTION_INHIBIT;
                packet->sp_Pkt.dp_Arg1 = flag;
                PutMsg(device,&packet->sp_Msg);
                WaitPort(reply);
                result = packet->sp_Pkt.dp_Res1;
                FreeMem((APTR)packet,(ULONG)sizeof(struct StandardPacket));
               }
             DeletePort(reply);
            }
        }
     return result;
     }

ReadTrack( cyl, buffer, diskreq )
register ULONG cyl;
register unsigned char *buffer;
register struct IOStdReq *diskreq;
       {
       diskreq->io_Length  = CYLSIZE;
       diskreq->io_Data    = (APTR)buffer;
       diskreq->io_Command = CMD_READ;
       diskreq->io_Offset  = cyl*CYLSIZE;
       DoIO(diskreq);
       if (diskreq->io_Error)
           {
            sprintf(&title[0],"ERROR READING TRACK : %ld",cyl); 
            printbox(&title[0],1L);
            return(ERROR);
           }

       return(NOERROR);
       }

FormatTrack( cyl, buffer, diskreq )
register ULONG cyl;
register unsigned char *buffer;
register struct IOStdReq *diskreq;
       {
       diskreq->io_Length  = CYLSIZE;
       diskreq->io_Data    = (APTR)buffer;
       diskreq->io_Command = TD_FORMAT;
       diskreq->io_Offset  = cyl*CYLSIZE;
       DoIO(diskreq);
       if (diskreq->io_Error)
           {
            sprintf(&title[0],"ERROR WRITING TRACK : %ld",cyl); 
            printbox(&title[0],1L);
            return(ERROR);
           }

       return(NOERROR);
       }
VerifyTrack( cyl ,buffer ,readbuffer ,diskreq )
register ULONG cyl;
register ULONG *buffer,*readbuffer;
register struct IOStdReq *diskreq;
       {
       register long fehler = NOERROR;
       register int i;
       register int j;
       
       BltClear(readbuffer,CYLSIZE,1L);
       j = CYLSIZE/4;
       if(ReadTrack(cyl,readbuffer,diskreq)== ERROR) fehler = ERROR;

       for (i=0;i<j;i++)
          {
            if (buffer[i] != readbuffer[i])
             {
             sprintf(&title[0],"ERROR VERIFYING TRACK : %ld",cyl); 
             printbox(&title[0],1L);
             fehler = ERROR;
             break;
             }
          }
       return(fehler);
       }
SignTrack(track)
register ULONG track;
       {
       MoveSprite(vp,&TrackSprite,(track*8L)-8L,10L);
       }
WriteBlock( block, buffer, diskreq )
register ULONG block;
register unsigned char *buffer;
register struct IOStdReq *diskreq;
       {
       diskreq->io_Length  = BLOCKSIZE;
       diskreq->io_Data    = (APTR)buffer;
       diskreq->io_Command = CMD_WRITE;
       diskreq->io_Offset  = block*BLOCKSIZE;
       DoIO(diskreq);
       if (diskreq->io_Error)  return (ERROR);

       return(NOERROR);
       }
ReadBlock( block, buffer, diskreq )
register ULONG block;
register unsigned char *buffer;
register struct IOStdReq *diskreq;
       {
       diskreq->io_Length  = BLOCKSIZE;
       diskreq->io_Data    = (APTR)buffer;
       diskreq->io_Command = CMD_READ;
       diskreq->io_Offset  = block*BLOCKSIZE;
       DoIO(diskreq);
       if (diskreq->io_Error)  return (ERROR);

       return(NOERROR);
       }
SwitchMotor(onoffswitch,diskreq)
register int onoffswitch;
register struct IOStdReq *diskreq;
       {
       diskreq->io_Length  = (long)onoffswitch;
       diskreq->io_Command = TD_MOTOR;
       DoIO(diskreq);
       }
ClearBuffer(diskreq)
register struct IOStdReq *diskreq;
       {
       diskreq->io_Command = CMD_CLEAR;
       DoIO(diskreq);
       }
 
HowManyDrives()
{
#define toAPTR(bptr) (APTR)(bptr<<2)
 register struct DeviceNode *list,*next;
 char name[5];
 ULONG *DosBase;
 register struct RootNode *root;
 register struct DosInfo *info;
 register char *ptr;
 register long drive,i;

 drive = 0L; 
 DosBase = (struct DosBase *)OpenLibrary("dos.library",0L);
 if(!DosBase)  return(0L);
 
 root = DosBase->dl_Root;
 info = toAPTR(root->rn_Info);
 list = toAPTR(info->di_DevInfo);

 while(list)
     {
      next = toAPTR(list->dn_Next);
      if(list->dn_Type == DLT_DEVICE)
          {
           ptr = toAPTR(list->dn_Name);
           ptr++;
           strncpy(&name[0],ptr,5);
           if(!strcmp("DF1",&name[0]))	drive = 2;
           if(!strcmp("DF2",&name[0])) 	drive = 3;
           if(!strcmp("DF3",&name[0])) drive = 4;
           if(!strcmp("CARD",&name[0]))	ramthere = TRUE;
          }
       list = next;
     }
 CloseLibrary(DosBase);
 for(i=0;i<drive;i++)
   {
    g_diskreq[i] = (struct IOStdReq *)TDOpen(i,device[0],port[i]);
    ForbidDrive(i,DOSTRUE);
   }
 if(ramthere)
  {
     g_diskreq[drive] = (struct IOStdReq *)TDOpen(0L,device[1],port[4]);
     strncpy(drives[drive],drives[4],3);
     return(drive);
  }
 else return(drive -1L);
}

DiskInDrive(source,dest,examine)
register struct IOStdReq *source,*dest;
register int examine;
     {
     source->io_Command = TD_CHANGESTATE;
     DoIO(source);
     if(source->io_Actual)
       {
        printbox("SOURCE DISK NOT INSERTED !!",1L);
        goto errextit;
       }
   if(!examine)
    {
     dest->io_Command = TD_CHANGESTATE;
     DoIO(dest);

     if(dest->io_Actual)
       {
        printbox("DESTINATION DISK NOT INSERTED !!",1L);
        goto errextit;
       }
     dest->io_Command = TD_PROTSTATUS;
     DoIO(dest);
     if(dest->io_Actual)
       {
        printbox("DESTINATION DISK WRITE PROTECTED !!",1L);
        goto errextit;
       }
    }
    return(NOERROR);
errextit:
    JaNein(&error[0]);
    IDCMPOff();
    return(ERROR);
   }
SearchBitMap(buffer,diskreq)
UBYTE *buffer;
struct IOStdReq *diskreq;
       {
       register long *bufflong = (long *)buffer;
       register int i;
       register int j;
       register ULONG dummy;
       register int block;

       BltClear(bitmapbuffer,1760L,1L);
       for (i=0;i<80;i++) trackbuffer[i] = 0;

       if(ReadBlock(880L,buffer,diskreq) == ERROR) return(ERROR);
       if(bufflong[78] != 0xffffffff) return (ERROR+1);
       bitblock = bufflong[79];
       if(ReadBlock(bitblock,buffer,diskreq) == ERROR) return(ERROR);

         bufflong[0] &=0x3fffffffL;
         dummy = 30L;
         for (i=0;i<80;++i)
           {
           for(j=0;j<22;j++)
             {
             block = (i*22)+j;
             if(bufflong[dummy/32L] & (1L << (dummy % 32L))) {;}
             else
                  {
                   bitmapbuffer[block] = 1;
                   if (!trackbuffer[block/22])
                           trackbuffer[block/22] = 1;
                  }
             ++dummy;
             }
           }
         bitmapbuffer[0] = 1;
	 bitmapbuffer[1] = 1;
	 trackbuffer[0] = 1;
        return(NOERROR);
        }

Initialize(drive)
register ULONG drive;
{
     register ULONG *formatbuffer = writebuffer;
     register ULONG *rootbuffer;
     register UBYTE *rb;
     register ULONG i,j;
     register ULONG class;
     register USHORT code,backcode;
     register BOOL Ende = FALSE;
     struct IntuiMessage *message;

     Request(&inidiskreq,window);
     SETDRMD(rp,JAM1);
     print(&newdiskname[0],200L,94L,0L);
     print(&newdiskname[0],201L,94L,1L);
     print(&ret[0],181L,137L,0L);
     print(&esc[0],411L,137L,0L);
     SETDRMD(rp,JAM2);
     box(170L,70L,470L,150L,2L);
     box(171L,71L,469L,149L,0L);
     BoxGadgets(&cancelgad,170L,70L,2L);
     box(199L,100L,440L,112L,2L);
     box(197L,98L,442L,117L,1L);

    while(!Ende)
     {
        if(key()==0x75){backcode = ESC;Ende = TRUE;}
        if(key()==0x77){backcode = RETURN;Ende = TRUE;}
         while(message = (struct IntuiMessage *)GetMsg(window->UserPort))
            {
            class = message->Class;
            ReplyMsg(message);
            switch (class)
              {
               case GADGETDOWN:
                    code = message->IAddress->GadgetID;
                    switch (code)
                       {
                       case NAME:
                       break;  
                       case ESC:
                         backcode = ESC;
                         Ende = TRUE;
                       break;
                       case RETURN:
                         backcode = RETURN;
                         Ende = TRUE;
                       break;
                      }
              }
           }
   } 
  EndRequest(&inidiskreq,window);
  if(backcode == ESC) goto oakidokie;

	for(i=0;i<1760;i++) blockmerker[i]=0;
	ClearBigDisplay();
	IDCMPOff();

	if(DiskInDrive(g_diskreq[drive],g_diskreq[drive],0)==ERROR) goto ade;

       	formatbuffer[0] = 0x444f5300;
 	bitbuffer  = (ULONG *)formatbuffer+128L;
	rootbuffer = (ULONG *)formatbuffer;
 	rb = (UBYTE *)formatbuffer;

 for(i=0;i<80;i++)
   {
    if(key()==0x75) goto ade;
    sprintf(&title[0],"FORMATTING TRACK : %ld     'ESC' TO ABORT",i);
    printbox(&title[0],1L);
    FormatTrack(i,formatbuffer,g_diskreq[drive]);
    if(verify)
       {
        sprintf(&title[0],"VERIFYING  TRACK : %ld     'ESC' TO ABORT",i);
        printbox(&title[0],1L);
        if(VerifyTrack(i,formatbuffer,verifybuffer,g_diskreq[drive])== ERROR)
         {
          for(j=0;j<22;j++)
           {
            blockmerker[i*22+j] = 1;
           }
         }
       }
   }  
   printbox("CREATING BITMAP",1L);
   rootbuffer[0]    = 2L;
   rootbuffer[127]  = 1L;
   rootbuffer[3]    = 72L;
   rootbuffer[78]   = 0xffffffff;
   rootbuffer[79]   = 881L;
   rb[432] = (UBYTE)strlen(&name[0]);
   strcpy(&rb[433],&name[0]);
   CorrectChecksum(rootbuffer,5);
   blockmerker[880]=1;
   blockmerker[881]=1;
   CreateBitMap();
   FormatTrack(40L,formatbuffer,g_diskreq[drive]);
ade:
     SwitchMotor(MOTOR_OFF,g_diskreq[drive]); 
oakidokie:
     IDCMPOn();
}

ExamineDisk(disk)
ULONG disk;
     {
     register ULONG i,j;
     register ULONG *blockbuffer;
     register UBYTE *bytebuffer = (ULONG *)writebuffer;
     UBYTE *merkbuffer;
     int err;

     ClearBigDisplay();

     if(DiskInDrive(g_diskreq[disk],0L,1)==ERROR) goto exitus;
     blockbuffer = (ULONG *)bytebuffer;
     merkbuffer = bytebuffer;

     ClearBuffer(g_diskreq[disk]);
     printbox(&readmap[0],1L);
     err = SearchBitMap(bytebuffer,g_diskreq[disk]);
      if (err == ERROR)
        {
         printbox(&bitmaperr[0],1L);
         JaNein(&error[0]);
         goto exitus;
        }
      if (err == ERROR+1)
        {
         printbox(&dnv[0],1L);
         JaNein(&error[0]);
         goto exitus;
        }
     ClearBuffer(g_diskreq[disk]);
     IDCMPOff();
     printbox("SCANNING DISK     'ESC' TO ABORT",1L);
     DisplaySprite();
     for (j=0;j<80;j++)
      {
       SignTrack(j);
       bytebuffer = merkbuffer;
       err = 0;
       if(ReadTrack(j,merkbuffer,g_diskreq[disk]) == ERROR)  err = 1;

       i = 0;
       do
        {
         if (err)
            if(ReadBlock(i+j*22,bytebuffer,g_diskreq[disk]) == ERROR)
              {print("E",trackpos[j],blockpos[i],2L);goto loop;}

         if (bitmapbuffer[i+j*22] == 0)
           {print("-",trackpos[j],blockpos[i],1L);goto loop;}
         if (bytebuffer[3] == 0x08 && bitmapbuffer[i+j*22] == 1)
           {print("+",trackpos[j],blockpos[i],1L);goto loop;}
         if (bytebuffer[3] == 0x02 && bytebuffer[511] == 0xfd)
           {print("F",trackpos[j],blockpos[i],3L);goto loop;}
         if (bytebuffer[3] == 0x10 && bytebuffer[511] == 0xfd)
           {print("L",trackpos[j],blockpos[i],3L);goto loop;}
         if (bytebuffer[3] == 0x02 && bytebuffer[511] == 0x02)
           {print("D",trackpos[j],blockpos[i],3L);goto loop;}
         if (bytebuffer[3] == 0x02 && bytebuffer[511] == 0x01)
           {print("R",trackpos[j],blockpos[i],3L);goto loop;}
         if (i+j*22 == bitblock)
           {print("M",trackpos[j],blockpos[i],3L);goto loop;}
         print("I",trackpos[j],blockpos[i],3L);

loop:    i++;
         bytebuffer = bytebuffer + 512;
         if (key()==0x75) goto exitus;
        } while (i<22);
      }
exitus:
     SwitchMotor(MOTOR_OFF,g_diskreq[disk]);
     FreeSprite(spritenr);
lexitus:
     IDCMPOn();
     }

Copy(source,destination)
ULONG source,destination;
     {
     ULONG *verifyreadbuffer = verifybuffer;
     register UBYTE *formatbuffer = (ULONG *)writebuffer;
     register UBYTE blitterdoit;
     register ULONG i,j,block;
     int err;
     ULONG *formatpointer[23];

     ClearBigDisplay();
     IDCMPOff();

     if(DiskInDrive(g_diskreq[source],g_diskreq[destination],0)==ERROR) goto abaway;
     ClearBuffer(g_diskreq[source]);
     ClearBuffer(g_diskreq[destination]);

     for(i=0;i<22;i++) formatpointer[i] = formatbuffer + (512*i);

     DisplaySprite();
     if(fastmode && !optimizer && !copymode) goto faster;
     printbox(&readmap[0],1L);
     err = SearchBitMap(formatbuffer,g_diskreq[source]);
      if (err == ERROR)
        {
         printbox(&bitmaperr[0],1L);
         JaNein(&error[0]);
         goto abgang;
        }
      if (err == ERROR+1)
        {
         printbox(&dnv[0],1L);
         JaNein(&error[0]);
         goto abgang;
        }
faster:    
     ClearBuffer(g_diskreq[source]);
     if(optimizer)
        {
         Optimize(g_diskreq[source],g_diskreq[destination]);
         goto abgang;
        }

     printbox("DISK COPY IN PROCESS     'ESC' TO ABORT",1L);
     if (fastmode) Fastmode(1);
     blitterdoit = err = 0;
     if(copymode)
     {
      for(i=0;i<80;i++)
        {
        SignTrack(i);
        if(blitterdoit)
            {BltClear(formatbuffer,CYLSIZE,1L);blitterdoit=err=0;}
         if(trackbuffer[i])
          {
           blitterdoit = 1;
           if(ReadTrack(i,formatbuffer,g_diskreq[source])==ERROR) err = 1;
           for(j=0;j<22;j++)
            {
             block = (i*22)+j;
             if(bitmapbuffer[block])
               {
               if(!err) if(!fastmode)print("+",trackpos[i],blockpos[j],1L);
               else
                 {
                 if(ReadBlock(block,formatpointer[j],g_diskreq[source])==ERROR)
                  {if(!fastmode)print("E",trackpos[i],blockpos[j],2L);goto hh1;}

                 if(!fastmode)print("+",trackpos[i],blockpos[j],1L);
 hh1: ;          }
               }
             else BltClear(formatpointer[j],BLOCKSIZE,1L);
            }
          }
        if (form)
             {
              FormatTrack(i,formatbuffer,g_diskreq[destination]);
              if (verify)
              VerifyTrack(i,formatbuffer,verifyreadbuffer,g_diskreq[destination]);
             }
        else
             {
             if (blitterdoit)
              {
              FormatTrack(i,formatbuffer,g_diskreq[destination]);
             if (verify)
              VerifyTrack(i,formatbuffer,verifyreadbuffer,g_diskreq[destination]);
              }
             }
        if(key() == 0x75) goto abgang;
        }
     }
     else
     {
     for (j=0;j<80;j++)
      {
        SignTrack(j);
        err = 0;
        if(ReadTrack(j,formatbuffer,g_diskreq[source]) == ERROR) err = 1;

        if (err || !fastmode)
        {
        i = 0;
        do
         {
           if (err)
              if(ReadBlock(i+j*22,formatpointer[j],g_diskreq[source]) == ERROR)
               if(!fastmode){print("E",trackpos[j],blockpos[i],2L);goto l2;}

           if (!fastmode)
            {
             if (bitmapbuffer[i+j*22])
               print("+",trackpos[j],blockpos[i],1L);
             else
               print("-",trackpos[j],blockpos[i],1L);
            }
l2:        i++;
         } while (i<22);
       }
      FormatTrack(j,formatbuffer,g_diskreq[destination]);
      if (verify) VerifyTrack(j,formatbuffer,verifyreadbuffer,g_diskreq[destination]);
      if(key() == 0x75) goto abgang;
      }
    }
abgang:
     if (fastmode) Fastmode(0);
     SwitchMotor(MOTOR_OFF,g_diskreq[source]);
     SwitchMotor(MOTOR_OFF,g_diskreq[destination]);
     FreeSprite(spritenr);
abaway:
     IDCMPOn();
 }

#asm
       public _key

_key   moveq #0,d0
       move.b $bfec01,d0
       rts
#endasm

main()
{
  register ULONG i = 0;

  if(!(IntuitionBase = (struct IntuitionBase *)
      OpenLibrary("intuition.library",0L))) NixDa();
  if(!(GfxBase = (struct GfxBase *)
      OpenLibrary("graphics.library",0L))) NixDa();
  anzahldrives = (long)HowManyDrives();
  if (anzahldrives < 1L) NixDa();

  for(i=0;i<80;i++) trackpos[i]=i*8L;
  for(i=0;i<22;i++) blockpos[i]=35L+(i*8L);
  if(!(screen = (struct Screen *)OpenScreen(&CopyScreen))) NixDa();
  CopyWindow.Screen = screen;
  rp    = (struct RastPort *) &screen->RastPort;
  vp    = (struct ViewPort *) &screen->ViewPort;
  LoadRGB4(vp,&colors[0],4L);
  if(!(window = (struct Window *)OpenWindow(&CopyWindow))) NixDa();
  Copper();
  if(!(writebuffer = (ULONG *)AllocMem(CYLSIZE,MEMF_CHIP|MEMF_CLEAR)))
     NixDa();
  if(!(verifybuffer= (ULONG *)AllocMem(CYLSIZE,MEMF_CHIP|MEMF_CLEAR)))
     NixDa();

  bitmapbuffer = (UBYTE *)AllocMem(1800L,MEMF_CHIP|MEMF_CLEAR);
  spritebuffer = (USHORT *)AllocMem(76L,MEMF_CHIP);

  for(i=0;i<38;i++) spritebuffer[i]=TrackSprite_dat[i]; 
  TrackSprite.posctldata = (UWORD *)spritebuffer;

  window->FirstGadget = (struct Gadget *)&go;
  RefreshGadgets((struct Gadget *)&go,window,0L);
  for(i=0;i<31;i++) copyright2[i] = (BYTE)copyright2[i]^i;
  Zeichne();
  HauptSchleife();
  NixDa();

}
NixDa()
     {
     register long i;

     if(ramthere) {
                   TDClose(g_diskreq[anzahldrives]);
    		   anzahldrives--;
                  }
     for(i=0;i<anzahldrives+1L;i++)
        {
         ForbidDrive(i,DOSFALSE);
         TDClose(g_diskreq[i]);
        }
     if (window)                   CloseWindow(window);
     if (screen)                   CloseScreen(screen);
     if (writebuffer)              FreeMem(writebuffer,CYLSIZE);
     if (verifybuffer)             FreeMem(verifybuffer,CYLSIZE);
     if (bitmapbuffer)             FreeMem(bitmapbuffer,1800L);
     if (spritebuffer)             FreeMem(spritebuffer,76L);
     if (IntuitionBase)            CloseLibrary(IntuitionBase);
     if (GfxBase)                  CloseLibrary(GfxBase);
     exit(0L);
     }
