#include <exec/types.h>
#include <exec/memory.h>
#include <exec/devices.h>
#include <exec/execbase.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <devices/trackdisk.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <stdio.h>
#include <string.h>
#include "BootBase.h"
#include "rawkey.h"

char IDstring[47] = {"BootBase V2.3 - Steven Lagerweij 5-apr-90"};

#define  BIG    1500L
#define  READ   1005L
#define  WRITE  1006L
#define  BUFFER    1024
#define  NUMHEADS  2
#define  PROTECT   "Disk is write-protected "
#define  NODISK    "No disk present.        "
#define  NOMEM     "Not enough memory.      "
#define  NOEXT     "Can't CreateExtIo().    "
#define  NOPORT    "Can't CreatePort().     "
#define  NOPROB    "No failures.            "
#define  NODEV     "Drive is occupied!      "
#define  EMPTY     "                        "
#define  CANCELED  10
#define  TOSHORT   20
#define  NOMATCH   30
#define  MATCH     40
#define  EXTSTAND  50
#define  NOINFO    60
#define  NOWIN     70

char seldr[8] = {" DFx "};                          /* active gadget text*/


extern struct ExecBase      *SysBase;        /* Libraries */
extern struct DosLibrary    *DOSBase;
       struct IntuitionBase *IntuitionBase;
       struct GfxBase       *GfxBase;

       struct Window        *OpenWindow();
void                        *OpenLibrary();
extern struct MsgPort       *CreatePort();
extern struct IORequest     *CreateExtIO();
       struct Message       *GetMsg();

       struct MsgPort       *diskport;
       struct IOExtTD       *diskreq;
       struct Screen        *screen;
       struct Window        *FirstWindow,*wlist,*reqwin;
       struct IntuiMessage  *message;
       struct Gadget        *GadgetPtr;
       struct IntuiText      DriveText =
                                { 2,3,JAM2, 0,0, NULL, &seldr[0], NULL };


ULONG  MessageClass;
USHORT code, GadgetID;
BYTE  *diskbuffer,Map[BUFFER];      /* Buffer for bootblock and file */
ULONG  diskchangecount,remcount[4]; /* Diskchangecounters to see which drive changed disk*/
long   drive = 0,availdrives[4];      /* Current drive and available drives */


char *ReqTexts[20] = {   /* Requester texts */
"You are about to rewrite  ",
"this disk's bootblock     ",
"Are you sure you want this ?",
"Do you wish to quit ?",
"There are windows/programs",
"which are NOT opened by me",
"Do you wish to QUIT or",
"REMOVE them first",
"Select YES to quit",
"NO to cancel",
};

BYTE standard[55] = {  /* Code for standard bootblock */
0x44,0x4f,0x53,0x00,0xc0,0x20,0x0f,0x19,0x00,0x00,0x03,0x70,
0x43,0xfa,0x00,0x18,0x4e,0xae,0xff,0xa0,0x4a,0x80,0x67,0x0a,
0x20,0x40,0x20,0x68,0x00,0x16,0x70,0x00,0x4e,0x75,0x70,0xff,
0x60,0xfa,0x64,0x6f,0x73,0x2e,0x6c,0x69,0x62,0x72,0x61,0x72,
0x79
}; /* the rest is filled with zeros */

char file[64];                                      /* Filereq */
char readdir[64] = {"BBS:"};                        /* Filereq */
char writedir[64] = {"BBS:"};                       /* FileReq */
char currcomment[81], Attached[128], tmp[100];      /* Comment, Filepath, temp store */
char kindofbb[100] = {"                         "}; /* BB Name */
char *Readptr,*Writeptr;                            /* Pointers for file operation */
char CompPath[5] = {"BBS:"};                        /* Logical assignment/path */
char *LeftMouse = (char *) 0xBFE001;                /* To test leftbutton directly, without intuitionmessage */

short comflag     = FALSE; /* Comment on ? */
short AutoCompare = FALSE; /* Flag for autocompare function */
short AutoRead    = FALSE; /* Flag for autoread bb from inserted disk */
short setupcnt    = TRUE;  /* Little flag to get diskchangecounts at startup */
short PAL         = TRUE;  /* PAL machine ? (see main()) */
short VisualComp  = FALSE;  /* If this flag is set the graphics will be printed */
short isthereabb  = FALSE; /* Is there a bootblock in buffer? - flag */

VOID _main()
{
   if(SysBase->VBlankFrequency != 0x32) PAL = FALSE;

   /* Find available drives */
   GadgetPtr = &StringGadget;
   if(FindUnit("DF0:"))
    { GadgetPtr->NextGadget = &df0gag; GadgetPtr = &df0gag; availdrives[0] = TRUE; }
   else availdrives[0] = FALSE;
   if(FindUnit("DF1:"))
    { GadgetPtr->NextGadget = &df1gag; GadgetPtr = &df1gag; availdrives[1] = TRUE; }
   else availdrives[1] = FALSE;
   if(FindUnit("DF2:"))
    { GadgetPtr->NextGadget = &df2gag; GadgetPtr = &df2gag; availdrives[2] = TRUE; }
   else availdrives[2] = FALSE;
   if(FindUnit("DF3:"))
    { GadgetPtr->NextGadget = &df3gag; availdrives[3] = TRUE; }
   else availdrives[3] = FALSE;
   if(!PAL)
     {
        FirstNewWindow.Height = 200;
        ns.Height             = 200;
     }
   Open_All();  /* Windows screen etc opened in here */

   DiskIns(); setupcnt = FALSE; /* Get change counts */
   drive = 1; GadgetID = 14; DriveSelect(); /* DF0 Active */

   LayOut(); /* Build screen outlay*/
   for(;;)
     {
      if ((message = (struct IntuiMessage *)
          GetMsg(FirstWindow->UserPort)) == NULL)
            {
                Wait(1<<FirstWindow->UserPort->mp_SigBit);
                continue;
            }
      MessageClass = message->Class;
      code      = message->Code;
      GadgetPtr = (struct Gadget *) message->IAddress;
      GadgetID  = GadgetPtr->GadgetID;
      ReplyMsg(message);


      switch (MessageClass)
         {
         case MOUSEBUTTONS: if(code == MENUDOWN)
                               Help(FirstWindow->MouseX,FirstWindow->MouseY);
                            break;
         case RAWKEY        : Do_RawKey(code);
                              break;
         case GADGETUP      : GadgetActs();
                              break;
         case DISKINSERTED  :
                              if(DiskIns() == 0)
                                {
                                  if(AutoRead) ErrPrint(ShowBootBlock());
                                }
                              break;

         }
     }
}


Open_All()
{

   if((diskbuffer = (BYTE *)
       AllocMem(BUFFER,MEMF_CHIP)) == NULL)
      {
      printf("Couldn't not allocate chip-memory for diskbuffer\n");
      exit(FALSE);
      }
   if (!(IntuitionBase = (struct IntuitionBase *)
         OpenLibrary("intuition.library", 0L)))
      {
      printf("Intuition Library failure!\n");
      Close_All();
      }
   if((GfxBase = (struct GfxBase *)
                    OpenLibrary("graphics.library",0)) == NULL)
      {
      printf("Can't open Graphics library!\n");
      Close_All();
      }
   if(!(screen=(struct Screen *)OpenScreen(&ns)))
   {
      printf("Can't open screen!\n");
      Close_All();
   }
   FirstNewWindow.Screen=screen;
   ReqWindow.Screen     =screen;

   if (!(FirstWindow = (struct Window *)OpenWindow(&FirstNewWindow)))
      {
      printf("Can't open Window!\n");
      Close_All();
      }
   return(0);
}

Close_All()   /* Everything that is opened will be closed */
{
short morewins = FALSE;
CLD();

if(screen)
  {
    for(wlist = screen->FirstWindow;wlist != NULL;wlist = wlist->NextWindow)
      {
        if(wlist != FirstWindow)
          {
            morewins++;
            Locate(4+morewins,2);
            sprintf(&tmp[0],"Error first remove window/program: %s",
                                                    (UBYTE *)wlist->Title);
            Print(&tmp[0]);
          }
      }
  }
   if((morewins) && (!AreYouSure(4,6,3))) return(FALSE);
   if(diskbuffer)       FreeMem(diskbuffer,BUFFER);
   if (FirstWindow)     CloseWindow(FirstWindow);
   if (GfxBase)         CloseLibrary(GfxBase);
   if (IntuitionBase)   CloseLibrary(IntuitionBase);
   if (screen)          CloseScreen(screen);
   exit(0);
}


Locate(y,x)  /* To locate the cursor for text printing */
short  y,x;
{
    short rx,ry;    /* Real x and y */
    rx=x*8;
    ry=y*8;
    ry=ry+16;
    if(ry<24)  ry=24;
    if(ry>248) ry=248;
    if(rx<1)   rx=1;
    if(rx>632) rx=632;

    if((!PAL) && (ry > 200)) ry = 200;
    Move(FirstWindow->RPort,rx,ry);
    return(0);
}

Print(line)   /* Print a string */
char line[100];
{
    Text(FirstWindow->RPort,&line[0],strlen(&line[0]));
    return(0);
}

ErrPrint(line)  /* Print string at specific position - errors fe. */
char *line;
{
    SetColor(1,0); Locate(3,12);
    Print("                                                 ");
    Locate(3,12); Print(&line[0]);
    return(0);
}

SetColor(f,b)
short    f,b;   /* Voor en achtergrondkleur */
{
    if(f<0 || f>3) f=1;
    if(b<0 || b>3) b=0;
    SetAPen(FirstWindow->RPort,f);
    SetBPen(FirstWindow->RPort,b);
    return(0);
}

ReadCylSec(cyl,sec,hd) /* Read 1024(BUFFER) bytes from disk */
SHORT cyl,sec,hd;
{
   LONG offset;

   diskreq->iotd_Req.io_Length = BUFFER;
   diskreq->iotd_Req.io_Data   = (APTR)diskbuffer;
   diskreq->iotd_Req.io_Command = ETD_READ;
   diskreq->iotd_Count = diskchangecount;
   offset = TD_SECTOR * (sec + NUMSECS * hd + NUMSECS * NUMHEADS * cyl);
   diskreq->iotd_Req.io_Offset = offset;
   DoIO(diskreq);
return(0);
}

MotorOn()  /* Drive motor on */
{
   diskreq->iotd_Req.io_Length  = 1;
   diskreq->iotd_Req.io_Command = TD_MOTOR;
   DoIO(diskreq);
return(0);
}

MotorOff()  /* Drive motor off */
{
   diskreq->iotd_Req.io_Length  = 0;
   diskreq->iotd_Req.io_Command = TD_MOTOR;
   DoIO(diskreq);
return(0);
}

struct IORequest *CreateExtIO(ioReplyPort,size) /* create extended I/O */
      struct MsgPort *ioReplyPort;
      LONG size;
{
      struct IORequest *ioReq;

   if(ioReplyPort == 0)
      return((struct IORequest *) 0);

   ioReq = (struct IORequest *)AllocMem (size,MEMF_CLEAR | MEMF_PUBLIC);
   if(ioReq==0)
      return((struct IORequest *) 0);
   ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
   ioReq->io_Message.mn_Node.ln_Pri = 0;
   ioReq->io_Message.mn_ReplyPort = ioReplyPort;
   return(ioReq);
}

DeleteExtIO(ioExt,size) /* Remove Extendend I/O */
   struct IORequest *ioExt;
   LONG size;
{
   ioExt->io_Message.mn_Node.ln_Type = 0xff;
   ioExt->io_Device = (struct Device *) -1;
   ioExt->io_Unit = (struct Unit *) -1;
   FreeMem(ioExt,size);
return(0);
}


ShowBootBlock()   /* Read bootblock from disk and show it on screen */
{
short readerr,tst;
char oneline[100];

   if((diskport = CreatePort(0,0)) == 0)
     { return(NOPORT); };

   if((diskreq = (struct IOExtTD *)
             CreateExtIO(diskport,sizeof(struct IOExtTD))) == NULL)
     { DeletePort(diskport); return(NOEXT);};

   if(OpenDevice(TD_NAME,drive,diskreq,0))
     {
       DeleteExtIO(diskreq,sizeof(struct IOExtID));
       DeletePort(diskport);
       return(NODEV);
     }
   diskreq->iotd_Req.io_Command = TD_CHANGESTATE;
   DoIO(diskreq);
   if(diskreq->iotd_Req.io_Actual != 0)
    {
       CloseDevice(diskreq);
       DeleteExtIO(diskreq,sizeof(struct IOExtTD));
       DeletePort(diskport);
       return(NODISK);
    }
   diskreq->iotd_Req.io_Command = TD_CHANGENUM;
   DoIO(diskreq);
   diskchangecount = diskreq->iotd_Req.io_Actual;
   remcount[drive] = diskchangecount;
   MotorOn();
   ReadCylSec(0,0,0);
   readerr=diskreq->iotd_Req.io_Error;
   MotorOff();
   if(readerr != 0)
      {
        CLD();
        sprintf(&oneline[0],"Read Error: %d",readerr);
        SetColor(3,0);
        if(isthereabb) PrintCurrentBB();
        return(&oneline[0]);
      }
   else
      {
        CLD();
        tst = CheckIfStandard();

        if(tst == 1)      sprintf(&kindofbb[0],"Standard 1.2/1.3         ");
        else if(tst == 2) sprintf(&kindofbb[0],"Do nothing bootblock     ");
        else              sprintf(&kindofbb[0],"Not identified !         ");
        isthereabb = TRUE;
        SetColor(1,0);
        PrintCurrentBB();
        if((AutoCompare) && (!tst)) DoComparing();
        else            Grafiek(1);
        StringBuffer[0] = '\0'; UndoBuffer[0] = '\0';
        RefreshGadgets(&StringGadget,FirstWindow,NULL);
      }
   CloseDevice(diskreq);
   DeleteExtIO(diskreq,sizeof(struct IOExtTD));
   DeletePort(diskport);
LayOut();
return(NOPROB);
}

CLD()
{
    SetColor(0,0);
    RectFill(FirstWindow->RPort,12,47,528,178);
    SetColor(1,0);
return(0);
}

PrintCurrentBB()
{
char oneline[100];
short ypos = 5,xpos;
short bufpos = 0;
int kar;
        for(bufpos=0;bufpos<1024;bufpos+=64)
          {
            for(xpos=0;xpos<64;xpos++)
              {
                kar = diskbuffer[(bufpos+xpos)];
                if((kar > 31) && (kar < 217)) oneline[xpos] = kar;
                else                          oneline[xpos] = '.';
              }
            oneline[64] = '\0';
            Locate(ypos,2); Print(&oneline[0]);
            ypos++;
          }
return(0);
}

LayOut()
{
    SetColor(2,0);
    DrawBox(10,45,530,180); /* Box around bootblock */
    DrawBox(11,46,529,179);

    DrawBox(10,13,530,45);  /* Box around error messages */
    DrawBox(11,14,529,44);

    DrawBox(541,17,639,43); /* Box around read/write boot gags */
    DrawBox(542,17,640,43); /* Box around read/write boot gags */

    DrawBox(541,43,639,72); /* Box around read/write file gadgets */
    DrawBox(542,43,640,72); /* Box around read/write file gadgets */

    SetColor(3,0);
    Locate(1,2); Print("Name    :                                         ");
    Locate(2,2); Print("Comment : ");
    Locate(3,2); Print("Error   : ");
    SetColor(1,0);
    Locate(1,12); Print(&kindofbb[0]);

    Move(FirstWindow->RPort,548,25); Print(" Bootblock");
    Move(FirstWindow->RPort,548,55); Print("   File   ");
    if(isthereabb) PrintCurrentBB();
    else {
        CLD();
        Locate(5,2); Print("BootBase v2.3 - by Steven Lagerweij");
        Locate(6,2); Print("Click with left button to perform the function");
        Locate(7,2); Print("Click with right button to see help about a function");
        Locate(8,2); Print("Press HELP to see the keys");
    }
return(0);
}

FindUnit(devname)
char devname[50];
{
struct   DeviceList    *zoekdev;
char isithim[50];
zoekdev = (struct DeviceList *) BADDR(((struct DosInfo *)
       BADDR(((struct RootNode *) (DOSBase->dl_Root))->rn_Info))->di_DevInfo);

while(zoekdev != 0)
    {
        sprintf(&isithim[0],"%s:",BADDR(zoekdev->dl_Name)+1);
        if((zoekdev->dl_Type == DLT_DEVICE) &&
           (stcpma(&devname[0],&isithim[0])))
            return(TRUE);
        zoekdev = (struct DeviceList *)BADDR(zoekdev->dl_Next);
    }
return(FALSE);
}


GadgetActs()
{

      switch(GadgetID)
        {
/* Read BB  */     case 1 :  ErrPrint(ShowBootBlock()); break;

/* Write BB */     case 2 :  if(AreYouSure(0,3,3)) WriteBootBlock(); break;

/*Read from file*/ case 3 :  ReadFile(); break;
/*Write to file*/  case 4 :  WriteToFile(); break;
/*Toggle compare*/ case 5 :  if(AutoCompare) AutoCompare = FALSE;
                             else            AutoCompare = TRUE;
                             break;
/*Toggle diskins*/ case 6 :  if(AutoRead) AutoRead = FALSE;
/*Auto read disk*/           else         AutoRead = TRUE;
                             break;
/* Quit */         case 7 :  if(AreYouSure(3,1,3)) Close_All(); break;
/* Noboot bb */    case 8 :  MakeNobootbuf(); Grafiek(1); break;
/* Standard bb*/   case 9 :  MakeStanbuf(); Grafiek(1); break;
/*Toggle comments*/case 10:  if(comflag) comflag = FALSE;
                             else        comflag = TRUE;
                             break;
/*DF0*/            case 14:
/*DF1*/            case 13:
/*DF2*/            case 12:
/*DF3*/            case 11:  DriveSelect(); break;
        }
return(0);
}


DriveSelect()
{
  long td;


    td = (GadgetID - 14) * -1;
    if((td < 0) || (!availdrives[td])) return(0);
    if(td == drive) return(0);

    drive = td; seldr[3] = '0'+drive;

    df0gag.GadgetText = &DF0Text; df1gag.GadgetText = &DF1Text;
    df2gag.GadgetText = &DF2Text; df3gag.GadgetText = &DF3Text;
    df0gag.GadgetRender = (APTR)&OffBorder;
    df1gag.GadgetRender = (APTR)&OffBorder;
    df2gag.GadgetRender = (APTR)&OffBorder;
    df3gag.GadgetRender = (APTR)&OffBorder;

    switch(drive)
      {
        case 0: df0gag.GadgetText = &DriveText;
                df0gag.GadgetRender = (APTR)&OnBorder; break;

        case 1: df1gag.GadgetText = &DriveText;
                df1gag.GadgetRender =  (APTR)&OnBorder; break;

        case 2: df2gag.GadgetText = &DriveText;
                df2gag.GadgetRender = (APTR)&OnBorder; break;

        case 3: df3gag.GadgetText = &DriveText;
                df3gag.GadgetRender = (APTR)&OnBorder; break;
      }
    SetColor(0,0); RectFill(FirstWindow->RPort,543,75,639,96);
    RefreshGadgets(&StringGadget,FirstWindow,NULL);
return(0);
}



DrawBox(x1,y1,x2,y2)
short x1,y1,x2,y2;
{
    Move(FirstWindow->RPort,x1,y1);
    Draw(FirstWindow->RPort,x2,y1);
    Draw(FirstWindow->RPort,x2,y2);
    Draw(FirstWindow->RPort,x1,y2);
    Draw(FirstWindow->RPort,x1,y1);
return(0);
}

WriteToFile()
{
   long ret;

   file[0] = '\0';

   if(!isthereabb)
     { ErrPrint("No bootblock available!"); return(FALSE); };

   ret = arpreq("Write bootblock to file", file, writedir, FirstWindow);
    if((ret != 0) && (file[0] != '\0'))
      {
        Koppel(&writedir[0],&file[0]);
        if((Writeptr = (char *)Open(&Attached[0],WRITE)) == 0L) goto quit;
        else {
          Write(Writeptr,diskbuffer,BUFFER);
          Close(Writeptr);
          if(comflag) SetComment(&Attached[0],&StringBuffer[0]);
          ErrPrint("written to file ok.");

        }
      }
quit:
   return(ret);
}

Koppel(dirname,filename)
char dirname[64],filename[64];
{
    if(dirname[0] == '\0')
       { sprintf(&Attached[0],"%s",&filename[0]); return(0); };

    if((dirname[strlen(&dirname[0])-1] != ':') &&
       (dirname[strlen(&dirname[0])-1] != '/'))
       sprintf(&Attached[0],"%s/%s",&dirname[0],&filename[0]);
    else                    /* ^ !!!! */
       sprintf(&Attached[0],"%s%s",&dirname[0],&filename[0]);

return(0);
}

CompWithFile()
{
   long ret,routret = FALSE,cntm = 0,largm = 0,larcnt = 0;
   short loop;

   if(!isthereabb) { ErrPrint("No bootblock available!"); return(0); }
   file[0] = '\0';

   sprintf(&kindofbb[0],"                              ");
   ret = arpreq("Select file to compare with bootblock", file, readdir, FirstWindow);

    if((ret != 0) && (file[0] != '\0'))
      {
        Koppel(&readdir[0],&file[0]);
        if((Readptr = (char *)Open(&Attached[0],READ)) == 0L) goto quit;
        else {
          if((Read(Readptr,Map,BUFFER)) != BUFFER)
               { Close(Readptr); routret = TOSHORT; goto quit; };
          Close(Readptr);
        }
       routret = MATCH;
       for(loop=0;loop<BUFFER;loop++)
        {
          if(diskbuffer[loop] != Map[loop])
            {
              routret = NOMATCH;
              if(larcnt > largm) largm = larcnt;
              larcnt = 0;
            }
          else { cntm++; larcnt++; }
        }
      }
    else { routret = CANCELED; goto quit; };
quit:
sprintf(&tmp[0],"Bytes matched: %-6ld, largest block %ld",cntm,largm);
if(routret == MATCH) sprintf(&kindofbb[0],"%-25s",&file[0]);
ErrPrint(&tmp[0]);
Grafiek(0);
return(routret);
}

ReadFile()
{
   long ret,routret = FALSE;
   short loop;

   file[0] = '\0';

   ret = arpreq("Select file to read as bootblock", file, readdir, FirstWindow);
   if((ret != 0) && (file[0] != '\0'))
    {
        Koppel(&readdir[0],&file[0]);
        if((Readptr = (char *)Open(&Attached[0],READ)) == 0L) {
            sprintf(&tmp[0],"Couldn't open '%s'",&Attached[0]);
            ErrPrint(&Attached[0]);
            goto quit;
        }
       ret = Read(Readptr,Map,BUFFER);
       Close(Readptr);
       if((ret == -1) || (ret != BUFFER)) goto quit;
       GetComment(&Attached[0]);
       routret = TRUE;
       for(loop=0;loop<BUFFER;loop++)
        diskbuffer[loop] = Map[loop];
       isthereabb = TRUE;
       sprintf(&kindofbb[0],"From file: %s  ",&file[0]);
       Grafiek(0);
       SetColor(1,0);
       PrintCurrentBB();
       LayOut();
    }
    else { routret = CANCELED; goto quit; };
quit:
if(!routret) ErrPrint("Error reading file!");
return(routret);
}



Help(x,y)
short x,y;
{
CLD();
SetColor(1,0);

if((x > 545) && (x < 590) &&
   (y >  30) && (y <  41))
    {
        Locate( 5,2); Print("Click on this gadget if you want to read");
        Locate( 6,2); Print("a bootblock from the selected drive");
        Locate( 7,2); Print("See Auto Comp.");
        Locate( 8,2); Print("If the program fails to read a");
        Locate( 9,2); Print("bootblock the previous bootblock is printed");
        Locate(10,2); Print("in the third color of your WB Colors");
    }

else if((x > 595) && (x < 635) &&
        (y >  30) && (y <  41))  /* WRITE BOOT */
    {
        Locate(5,2); Print("Click on this gadget if you want to write");
        Locate(6,2); Print("current bootblock to the selected drive");
    }

else if((x > 595) && (x < 635) &&
        (y >  60) && (y <  71)) /* WRITE FILE */
    {
        Locate(5,2); Print("If you select this gadget you'll be asked");
        Locate(6,2); Print("for a filename. Then this program will");
        Locate(7,2); Print("write the current bootblock to that file");
    }
else if((x > 545) && (x < 690) &&
        (y >  60) && (y <  71))  /* READ FILE */
    {
        Locate(5,2); Print("This function reads a file as a bootblock");
        Locate(6,2); Print("So you can write it to disk");
    }

else if((x >  10) && (x < 530) &&
        (y >  45) && (y < 180))  /* bootblock */
    {
        Locate(5,2); Print("This box will be used for the display");
        Locate(6,2); Print("of results from several functions.");
        Locate(7,2); Print("READ BOOT fe. uses it to display the ASCII");
        Locate(8,2); Print("dump of the bootblock");
    }
else if((x >  10) && (x < 530) &&
        (y >  15) && (y <  45)) /* Box around error messages */
    {
        Locate( 5,2); Print("That box is used to display the name and");
        Locate( 6,2); Print("comment of a file that you've red with");
        Locate( 7,2); Print("read-file or the name of the file that matches");
        Locate( 8,2); Print("the current bootblock");
        Locate(09,2); Print("Errors are printed here and the comment can be");
        Locate(10,2); Print("changed (Saved only if Comment is ON)");
    }
else if((x > 545) && (x < 640) &&
        (y > 146) && (y < 157))
    {
        Locate( 5,2); Print("This gadget is a gadget, that toggles");
        Locate( 6,2); Print("Auto Compare. If this gadget is toggled");
        Locate( 7,2); Print("to ON and you select READ BOOT,");
        Locate( 8,2); Print("this program will automaticly search ");
        Locate( 9,2); Print("and compare any file which is found");
        Locate(10,2); Print("in a directory called BBS:. with the current");
        Locate(11,2); Print("bootblock. If a file totally (1024 bytes) matches");
        Locate(12,2); Print("his name will appear.");
        Locate(13,2); Print("If not 'Not Identified !' will be printed on that place");
        Locate(15,2); Print("The search and compare sequence can be aborted");
        Locate(16,2); Print("at any time by pressing and holding");
        Locate(17,2); Print("the Left button until he aborted");
    }
else if((x >   0) && (x < 640) &&
        (y > 185) && (y < 250) && (PAL)) /* grafieken */
    {
        Locate( 5,2); Print("That area is used for two graphics which");
        Locate( 6,2); Print("represent 1024 bytes. The lower one is always");
        Locate( 7,2); Print("in the second color of your WB Colors, and");
        Locate( 8,2); Print("it represents the current bootblock");
        Locate( 9,2); Print("The upper represents the current file");
        Locate(10,2); Print("and will be printed in the the same color as");
        Locate(11,2); Print("the bootblock if that byte matches the byte");
        Locate(12,2); Print("from the bootblock. if not the color is the");
        Locate(13,2); Print("third color of your WB Colors (Cursor in CLI)");
        Locate(14,2); Print("This can be turned off by pressing F10");
    }
else if((x > 535) && (x < 640) &&
        (y > 134) && (y < 145))
    {
        Locate( 5,2); Print("When you activate the auto read option");
        Locate( 6,2); Print("the program reads any bb from any disk");
        Locate( 7,2); Print("that is inserted");
    }
else if((x > 535) && (x < 640) && (y > 111) && (y < 121))
    {
        Locate( 5,2); Print("Pressing this gadget gives you a do nothing");
        Locate( 6,2); Print("bootblock, which can be written to disk");
    }
else if((x > 535) && (x < 640) && (y > 99) && (y < 109))
    {
        Locate( 5,2); Print("Pressing this gadget gives you a standard");
        Locate( 6,2); Print("bootblock, which can be written to disk");
    }
else if((x > 535) && (x < 640) && (y > 122) && (y < 132))
    {
        Locate( 5,2); Print("If this gadget is activated the program");
        Locate( 6,2); Print("writes the contents of the comment");
        Locate( 7,2); Print("(string) gadget to the file if you");
        Locate( 8,2); Print("select write to file");
    }
else if((x > 535) && (x < 640) && (y > 159) && (y < 169))
    {
        Locate( 5,2); Print("There is only one thing special about quit");
        Locate( 6,2); Print("Since the screen of BootBase is a");
        Locate( 7,2); Print("WBENCHSCREEN other programs that normally");
        Locate( 8,2); Print("open their window on the WBench could open");
        Locate( 9,2); Print("up on this screen, so when you quit");
        Locate(10,2); Print("You'll be asked to remove those windows first");
        Locate(11,2); Print("You don't have to do this but if you can");
        Locate(12,2); Print("it is better to do so");
        Locate(14,2); Print("Try this and you understand what I mean ");
        Locate(15,2); Print("Make sure this screen is the most front screen");
        Locate(16,2); Print("pull this screen down so you can click on a");
        Locate(17,2); Print("WBench drawer Icon, you'll see that the drawer");
        Locate(18,2); Print("window opens on BootBase' screen");
    }
else LayOut();
return(0);
}

Grafiek(which)
short which;
{

    short ybase;
    short x,p;
    short addy;

    if((!VisualComp) || (!PAL)) return(0);

    if(which == 9) goto Graph2;
    ybase = 235; p = 0; x = 10; addy = 0;
    SetColor(0,0); RectFill(FirstWindow->RPort,0,217,640,250);
    if(which > 1) goto Graph2;

    Move(FirstWindow->RPort,0,ybase);
    SetColor(2,0);
    while(x < 522)
      {
        addy = diskbuffer[p]/10;
        Draw(FirstWindow->RPort,x,ybase+addy);
        addy = diskbuffer[p+1]/10;
        Draw(FirstWindow->RPort,x,ybase+addy);
        x++; p+=2;
      }

Graph2:
    SetColor(0,0); RectFill(FirstWindow->RPort,0,185,640,217);
    ybase = 200; x = 10; p = 0; addy = 0;
    if(which == 1) goto quit;
    Move(FirstWindow->RPort,0,ybase);
    while(x < 522)
      {
        if((diskbuffer[p] == Map[p]) || (diskbuffer[p+1] == Map[p+1]))
            SetColor(2,0);
        else SetColor(3,0);
        addy = Map[p]/10;
        Draw(FirstWindow->RPort,x,ybase+addy);
        addy = Map[p+1]/10;
        Draw(FirstWindow->RPort,x,ybase+addy);
        x++; p+=2;
      }
quit:
return(0);
}



DoComparing()
{
struct   Lock          *disklock;
struct   FileInfoBlock *fib;
short flag;
short loop;

   fib = 0;
   disklock = 0;

   if((fib = (struct FileInfoBlock *)
       AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR)) == 0) goto quit;

   if((disklock = (struct Lock *)
       Lock(&CompPath[0],SHARED_LOCK)) == 0) goto quit;

   if(!Examine(disklock,fib)) goto quit;
   if(fib->fib_DirEntryType < 0) goto quit;

   Grafiek(1);
   while(ExNext(disklock, fib))
    {
        if(fib->fib_DirEntryType > 0) goto next;
        Koppel(&CompPath[0],fib->fib_FileName);
        if((Readptr = (char *)Open(&Attached[0],READ)) == 0L) goto quit;
        else if((Read(Readptr,Map,BUFFER)) != BUFFER)
                { Close(Readptr); goto next; };
        Close(Readptr);
        sprintf(&tmp[0],"Comparing with %s",fib->fib_FileName);
        ErrPrint(&tmp[0]);
        flag = TRUE;
        for(loop=0;loop<BUFFER;loop++)
          if(diskbuffer[loop] != Map[loop])
            { flag = FALSE; break; };
        Grafiek(9);
        if(flag)
          {
            sprintf(&kindofbb[0],"%-25s",fib->fib_FileName);
            goto quit;
          }
        if(((*LeftMouse & 0x40) != 0x40) &&
           (IntuitionBase->ActiveWindow == FirstWindow)) goto quit;
next:
    }
   sprintf(&kindofbb[0],"Not identified !         ");
quit:
   if(flag) GetComment(&Attached[0]);
   if (disklock) UnLock(disklock);
   if(fib)       FreeMem(fib,sizeof(fib));
   LayOut();
return(0);
}


WriteBootBlock()
{
short writeerr;
char oneline[100];

   if(!isthereabb)
     { ErrPrint("No bootblock available!"); return(FALSE); };
   if((diskport = CreatePort(0,0)) == 0)
     { ErrPrint(NOPORT); return(FALSE); };

   if((diskreq = (struct IOExtTD *)
             CreateExtIO(diskport,sizeof(struct IOExtTD))) == NULL)
                  { DeletePort(diskport); ErrPrint(NOEXT); return(FALSE); }

   if(OpenDevice(TD_NAME,drive,diskreq,0))
     {
       DeleteExtIO(diskreq,sizeof(struct IOExtID));
       DeletePort(diskport);
       ErrPrint(NODISK);
     }

   diskreq->iotd_Req.io_Command = TD_CHANGESTATE;
   DoIO(diskreq);
   if(diskreq->iotd_Req.io_Actual != 0)
    {
       CloseDevice(diskreq);
       DeleteExtIO(diskreq,sizeof(struct IOExtTD));
       DeletePort(diskport);
       ErrPrint(NODISK);
       return(FALSE);
    }
   diskreq->iotd_Req.io_Command = TD_PROTSTATUS;
   DoIO(diskreq);
   if(diskreq->iotd_Req.io_Actual != 0)
    {
       CloseDevice(diskreq);
       DeleteExtIO(diskreq,sizeof(struct IOExtTD));
       DeletePort(diskport);
       ErrPrint(PROTECT);
       return(FALSE);
    }

   diskreq->iotd_Req.io_Command = TD_CHANGENUM;
   DoIO(diskreq);
   diskchangecount = diskreq->iotd_Req.io_Actual;

   MotorOn();
   writeerr = WriteCylSec(0,0,0);
   MotorOff();
   if(writeerr > 19)
      {
        CLD();
        sprintf(&oneline[0],"Write Error: %-7d",writeerr);
        Print(&oneline[0]);
        SetColor(3,0);
        if(isthereabb) PrintCurrentBB();
      }
   else
      {
        CLD();
        ErrPrint("Written to disk Ok.     ");
        SetColor(1,0);
        PrintCurrentBB();
        Grafiek(1);
        StringBuffer[0] = '\0'; UndoBuffer[0] = '\0';
        RefreshGadgets(&StringGadget,FirstWindow,NULL);
      }
   CloseDevice(diskreq);
   DeleteExtIO(diskreq,sizeof(struct IOExtTD));
   DeletePort(diskport);
return(NOPROB);
}

WriteCylSec(cyl,sec,hd)
SHORT cyl,sec,hd;
{
   LONG offset;

   diskreq->iotd_Req.io_Length = BUFFER;
   diskreq->iotd_Req.io_Data   = (APTR)diskbuffer;
   diskreq->iotd_Req.io_Command = ETD_WRITE;
   diskreq->iotd_Count = diskchangecount;
   offset = TD_SECTOR * (sec + NUMSECS * hd + NUMSECS * NUMHEADS * cyl);
   diskreq->iotd_Req.io_Offset = offset;
   DoIO(diskreq);
   diskreq->iotd_Req.io_Command = CMD_UPDATE;
   DoIO(diskreq);
return(diskreq->iotd_Req.io_Error);
}


MakeNobootbuf()
{
    short loop;

    for(loop=0;loop<1024;loop += 4)
      {
        diskbuffer[loop]   = 'D';
        diskbuffer[loop+1] = 'O';
        diskbuffer[loop+2] = 'S';
        diskbuffer[loop+3] = 0x00;
      }
    sprintf(&kindofbb[0],"Do nothing bootblock     ");
    isthereabb = TRUE;
    LayOut();
return(0);
}

MakeStanbuf()
{
    short loop;

    sprintf(&kindofbb[0],"Standard 1.2/1.3         ");
    for(loop=0;loop<1024;loop++)
      {
        if(loop < 49) diskbuffer[loop] = standard[loop];
        else          diskbuffer[loop] = 0x00;
      }
    isthereabb = TRUE;
    LayOut();
return(0);
}


CheckIfStandard()
{
short loop,chk = TRUE;

    for(loop=0;loop<1024;loop++)
      {
        if((loop < 49) && (diskbuffer[loop] != standard[loop])) chk = FALSE;
        else if((loop >= 49) && (diskbuffer[loop] != 0x00))     chk = FALSE;
      }
    if(chk == TRUE) return(1);

    chk = TRUE;
    for(loop=0;loop<1024;loop += 4)
      {
        if((diskbuffer[loop]   != 'D') ||
           (diskbuffer[loop+1] != 'O') ||
           (diskbuffer[loop+2] != 'S')) { chk = FALSE; break; };
        /* There is no test for diskbuffer[loop+3] because I've seen
           a lot of different versions and it doesn't really matter
           what's at this location, it can't be a virus or an executable */

      }
    if(chk == TRUE) return(2);
    return(0);
}

AreYouSure(txtno,txtlen,col)
short txtno,txtlen,col;
{
short x,y,start;
long ret = FALSE;
long ledge,tedge,maxy = 256;
    if(!PAL) maxy = 200;
    ledge = FirstWindow->MouseX-265;
    tedge = FirstWindow->MouseY-50;
    if(ledge < 0) ledge = 0;
    if(ledge > 335) ledge = 335;
    if(tedge < 0) tedge = 0;
    if(tedge > maxy-100) tedge = maxy-100;
    ReqWindow.LeftEdge = ledge;
    ReqWindow.TopEdge  = tedge;
    if(!(reqwin = (struct Window *)OpenWindow(&ReqWindow))) return(FALSE);

    if(txtlen > 6) txtlen = 6;
    SetColor(col,0);
    x = 10;
    start = 20+(((6-txtlen)/2)*8);
    for(y=txtno;y<(txtno+txtlen);y++)
      {
        Move(reqwin->RPort,x,start+((y-txtno)*8));
        Text(reqwin->RPort,ReqTexts[y],strlen(ReqTexts[y]));
      }

    for(;;)
     {
      if ((message = (struct IntuiMessage *)
          GetMsg(reqwin->UserPort)) == NULL)
            {
                Wait(1<<reqwin->UserPort->mp_SigBit);
                continue;
            }
      MessageClass = message->Class;
      code      = message->Code;
      GadgetPtr = (struct Gadget *) message->IAddress;
      GadgetID  = GadgetPtr->GadgetID;
      ReplyMsg(message);


      switch (MessageClass)
         {
         case GADGETUP      :
                              if(GadgetID == 1) { ret = (TRUE); goto quit; }
                              else if(GadgetID == 2) { ret = FALSE; goto quit; }
                              break;

         }
     }
quit:
    if(reqwin) CloseWindow(reqwin);
    return(ret);
}



DiskIns()
{
    short lus,cd = FALSE;

    if((diskport = CreatePort(0,0)) == 0) return(NOPORT);
    if((diskreq = (struct IOExtTD *)
      CreateExtIO(diskport,sizeof(struct IOExtTD))) == NULL)
        { DeletePort(diskport); return(NOEXT);};

    for(lus = 0;lus < 4;lus++)
        {
            if(!availdrives[lus]) continue;
            OpenDevice(TD_NAME,lus,diskreq,0);

            diskreq->iotd_Req.io_Command = TD_CHANGESTATE;
            DoIO(diskreq);

            if(diskreq->iotd_Req.io_Actual != 0)
              { CloseDevice(diskreq); continue; }

            diskreq->iotd_Req.io_Command = TD_CHANGENUM;
            DoIO(diskreq);
            diskchangecount = diskreq->iotd_Req.io_Actual;
            CloseDevice(diskreq);
            if(!setupcnt)
              {
              if(remcount[lus] != diskchangecount)
                {
                  if(AutoRead)
                      {  GadgetID = 14 - lus; DriveSelect(); };
                  cd = TRUE;
                  remcount[lus] = diskchangecount;
                  goto quit;
                }
              }
            else remcount[lus] = diskchangecount;
        }
quit:
   DeleteExtIO(diskreq,sizeof(struct IOExtTD));
   DeletePort(diskport);
   if(cd) return(0);
   return(TRUE);
}


GetComment(whichfile)
char whichfile[200];
{
struct   Lock          *disklock;
struct   FileInfoBlock *fib;

   short ret = 0;
   fib = 0;
   disklock = 0;

   if((fib = (struct FileInfoBlock *)
       AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR)) == 0) goto quit;

   if((disklock = (struct Lock *)
       Lock(&whichfile[0],SHARED_LOCK)) == 0) goto quit;

   if(!Examine(disklock,fib)) goto quit;
   sprintf(&StringBuffer[0],"%s",fib->fib_Comment);
   RefreshGadgets(&StringGadget,FirstWindow,NULL);
   ret = 1;

quit:
   if (disklock) UnLock(disklock);
   if(fib)       FreeMem(fib,sizeof(fib));
return(ret);
}

PrintKeys()
{
CLD();

    Locate(5,10); Print("Available keys (RAWKEY)");
    Locate(6,2);  Print("F1   =  Compare with file; Sorry no gadget!");
    Locate(7,2);  Print("F9   =  Redraw");
    Locate(8,2);
    if(PAL)     { Print("F10  =  toggle graphics"); Locate(9,2); }
                  Print("ESC  =  Quit");
return(0);
}

Do_RawKey(key)  /* Perform actions on certain keys */
USHORT key;
{
    switch(key)
        {
            case F1     : CompWithFile();
                          break;
            case F9     : RefreshGadgets(&ReadBB,FirstWindow,NULL);
                          LayOut(); Grafiek(0); break;
            case F10    :
                          if(PAL)
                            {
                              if(VisualComp) {
                                   VisualComp = FALSE;
                                   SetColor(0,0);
                                   RectFill(FirstWindow->RPort,0,180,640,250);
                                   SetColor(1,0);
                              }
                              else { VisualComp = TRUE; Grafiek(0); }
                            }
                          break;
            case ESC    : if(AreYouSure(3,1,3)) Close_All(); break;
            case HELP   : PrintKeys();
                          break;
        }
    return(0);
}


