char *stx[]={ " Pcopy 1.0 1 April 88 by D.Reisig", " Pcopy 1.0 is PD", " Made in Holland!" }; #include "pcopy.h" /* * Since no commandline parameters are processed, we may prevent * a call to exit(), by defining _main() here. * * We do a call to Init() which sets up all I/O, check patching * sceentitles, loop copy function and if desired, a call to Quit() * which returns all memory and closes all I/O. */ _main() { register struct IntuiMessage *Mesg; register int message; if (!Init()){ SetWindowTitles(WT,-1,stx[0]); SetWindowTitles(W1,-1,stx[1]); SetWindowTitles(W0,-1,stx[2]); ConPutStr(IOHist,"\x9b0 p\n\n\n\n\n\n "); while(1){ MainLoop(); Mesg=GetMsg(WS->UserPort); if (Mesg){ message=Mesg->Class; ReplyMsg(Mesg); if (message==CLOSEWINDOW){ if (!Request(" Pcopy","","stay","away")) break; } } } } Quit(); /* return and close everything */ return(0); } /* _main */ /* * See if somthing happend in the command window, check drives and * set "Now in .." windows. Finally check if a start copy condition * became valid. */ void MainLoop() { static int d0cnt=-1, d1cnt=-1; CheckControl(1); /* some user command? */ if (GetDrive(D0)){ /* disk is present */ if (d0cnt!=D0->ChgNum){ ShDName(W0,D0->VolName); d0cnt=D0->ChgNum; } } else{ /* disk is absent */ ShDName(W0,0); EnAuto=-1; /* enable auto start */ } if (GetDrive(D1)){ if (d1cnt!=D1->ChgNum){ ShDName(W1,D1->VolName); d1cnt=D1->ChgNum; } } else{ ShDName(W1,0); EnAuto=-1; } CheckCopy(); } /* MainLoop() */ /* * React upon windowsizing of the history window. * The gadgets are scanned and some minor (mostly intuition-patches) * actions are taken. Did I do it wrong or isn't intuition that good? */ void CheckControl(flag) short flag; { static short Excla=0, HistH=HHS; if (HistH!=WH->Height){ HistH=WH->Height; RefHist(); } /* NowCopy tells us which picture presently is displayed */ if (GAuto.Flags&SELECTED){ if (NowCopy){ RemoveGadget(WS,&GCopy); /* remove manual start */ GCopy.Flags&=~SELECTED; /* no surprises when changed back! */ DrawImage(WS->RPort,&IMBlnk,16,4*GGH); /* clear area */ PrintIText(WS->RPort,&ITCCon,16,4*GGH+2); AddGadget(WS,&GUnRd,-1); AddGadget(WS,&GNDOS,-1); RefreshGadgets(&GUnRd,WS,0); NowCopy=0; } } else{ if (!NowCopy){ RemoveGadget(WS,&GNDOS); RemoveGadget(WS,&GUnRd); DrawImage(WS->RPort,&IMBlnk,16,4*GGH); AddGadget(WS,&GCopy,-1); RefreshGadgets(&GCopy,WS,0); NowCopy=1; } } if ((GAuto.Flags&SELECTED) /* check for dangerous condition */ &&!(GNDOS.Flags&SELECTED) &&!(GUnRd.Flags&SELECTED)){ if (!Excla){ /* display alarming exclamation */ DrawImage(WS->RPort,&IMEcla,160,5*GGH); Excla=1; } }else if (Excla){ /* or remove it */ DrawImage(WS->RPort,&IMEcOf,160,5*GGH); Excla=0; } if (GD0D1.Flags&SELECTED){ /* set colors and arrow according to */ ITDr0.FrontPen=PenB; /* selected direction */ ITDr1.FrontPen=PenA; /* if selected, change state and deselect */ GD0D1.GadgetRender=ArrowB; /* again */ GD0D1.SelectRender=ArrowA; ArrowA=GD0D1.GadgetRender; ArrowB=GD0D1.SelectRender; PenA=ITDr0.FrontPen; PenB=ITDr1.FrontPen; GD0D1.Flags&=~SELECTED; /* if done deselect gadget */ RefOneGadget(&GD0D1,WS,0); } /* refresh (deghost) window titles */ if (!flag){ /* track window with or without depth g's */ TxT[SHORTTIME]=' '; DrawImage(WT->RPort,&IMTTTL,0,0); DrawImage(WT->RPort,&IMTTTL,0,9); PrintIText(WT->RPort,&ITT,4,1); } else{ TxT[SHORTTIME]='\0'; PrintIText(WT->RPort,&ITT,4,1); } PrintIText(WH->RPort,&ITH,4,1); PrintIText(W1->RPort,&IT1,4,1); PrintIText(W0->RPort,&IT0,4,1); } /* CheckControl */ /* * Gather all possible info of a drive and return disk presence. */ GetDrive(drive) register DrInfo *drive; { register char *name=(char *)(&CopyBuffer[ROOT_VOLNAME]); register int error; drive->Req.io_Command=TD_CHANGESTATE; DoIO(&drive->Req); /* is there a disk? */ if (drive->Present=~drive->Req.io_Actual){ drive->Req.io_Command=TD_CHANGENUM; DoIO(&drive->Req); /* did we check it already? */ if (drive->ChgNum!=drive->Req.io_Actual){ /* no .. */ drive->ChgNum=drive->Req.io_Actual; drive->DOSDisk=0; drive->DOSBoot=0; drive->Readable=0; error=ReadSec(drive,0,CopyBuffer); /* readable? */ if (!error||(error!=TDERR_NoSecHdr)){ drive->Readable=-1; if (!error&&((*CopyBuffer==0x444f5300)||(*CopyBuffer==0x4b49434b))){ drive->DOSBoot=-1; /* DOS\0 or KICK */ if (!ReadSec(drive,ROOTSECTOR,CopyBuffer) &&!CheckSum(CopyBuffer)&&(*nameDOSDisk=-1; /* Truly Amiga-DOS */ strncpy(drive->VolName,name+1,*name); drive->VolName[*name]='\0'; } else strcpy(drive->VolName,"\x0eNear DOS"); } else strcpy(drive->VolName,"\x0eNon DOS"); } else strcpy(drive->VolName,"\x0eUnreadable"); MotorOff(drive); } /* end of other chgnum */ } else drive->Present=0; return ((int)drive->Present); } /* GetDrive() */ ReadSec(drive,sector,buffer) register DrInfo *drive; SHORT sector; char *buffer; { drive->Req.io_Command=CMD_READ; drive->Req.io_Data=(APTR)buffer; drive->Req.io_Length=TD_SECTOR; drive->Req.io_Offset=sector*TD_SECTOR; DoIO(&drive->Req); return((int)drive->Req.io_Error); } /* * The checksum is OK if we add all longwords in a sector and its * result is zero. */ CheckSum(Sector) register ULONG *Sector; { register ULONG Sum; register short i; for (Sum=0,i=0;iRPort,&IMBlnk,16,4*GGH); RefOneGadget(&GCopy,WS,0); } D0->Count=D0->ChgNum; /* set up for Extended Command */ D1->Count=D1->ChgNum; if (mod==WAIT){ /* Special case, see manual */ DisplayBeep(IntuitionBase->ActiveScreen); Delay(100); } /* This is the cylinder counting loop */ for (cylinder=0,byte=0;cylinderRPort,&IMTmOn,cylinder*4,12); /* track window */ ReadSource: if (error=DIOCyl(Source,byte,CopyBuffer,ETD_READ)){ stci_d(stpcpy(Errbuf0,"Source read error # "),error); stci_d(stpcpy(Errbuf1,"On cylinder # "),cylinder); Beep(); if (Request(Errbuf0,Errbuf1,"retry","abort")) goto ReadSource; else break; } if (cylinder==ROOTCYL){ ChangeRoot(CopyBuffer); strncpy(Dest->VolName,name+1,*name); Dest->VolName[*name]='\0'; Dest->DOSDisk=-1; } WriteDestination: if (error=DIOCyl(Dest,byte,CopyBuffer,ETD_FORMAT)){ stci_d(stpcpy(Errbuf0,"Destination write error # "),error); stci_d(stpcpy(Errbuf1,"On cylinder # "),cylinder); Beep(); if (Request(Errbuf0,Errbuf1,"retry","abort")) goto WriteDestination; else break; } if (GVerf.Flags&SELECTED){ Dest->Req.io_Command=ETD_CLEAR; DoIO(&Dest->Req); if (error=DIOCyl(Dest,byte,CompBuffer,ETD_READ)){ stci_d(stpcpy(Errbuf0,"Destination read error # "),error); stci_d(stpcpy(Errbuf1,"On cylinder # "),cylinder); Beep(); if (Request(Errbuf0,Errbuf1,"retry","abort")) goto WriteDestination; else break; } if (Compare(CopyBuffer,CompBuffer)){ stci_d(stpcpy(Errbuf1,"On cylinder # "),cylinder); Beep(); if (Request("Verification error",Errbuf1,"retry","abort")) goto WriteDestination; else break; } } } /* end of cylinder count loop */ /* copy done */ DrawImage(WT->RPort,&IMTmOf,0,12); /* clear track window */ RefreshWindowFrame(WT); /* depth gadgets back */ if (!error){ ConPutStr(IOHist,"\n "); ConPutStr(IOHist,Dest->VolName); EnterHist(Dest->VolName); Beep(0); } else{ strcpy(Dest->VolName,"\x0eCopy unsuccesful"); Dest->DOSDisk=0; } ShDName(W0,D0->VolName); ShDName(W1,D1->VolName); MotorOff(Source); MotorOff(Dest); OnGadget(&GD0D1,WS,0); /* enable direction selection */ GCopy.Flags&=~GADGDISABLED; if (NowCopy){ /* that intuition patch again */ DrawImage(WS->RPort,&IMBlnk,16,4*GGH); RefOneGadget(&GCopy,WS,0); } return(error); } /* DiskCopy */ /* * Read or write one cylinder. */ DIOCyl(drive,byte,buffer,cmd) register DrInfo *drive; ULONG byte; char *buffer; int cmd; { drive->Req.io_Command=cmd; drive->Req.io_Data=(APTR)buffer; drive->Req.io_Length=BPCYL; drive->Req.io_Offset=byte; SendIO(&drive->Req); CheckControl(0); /* see if things did change (without track dg's) */ WaitIO(&drive->Req); return((int)drive->Req.io_Error); } Compare(a,b) register ULONG *a, *b; { register int i; for (i=0;i<(BPCYL/4);++i) if (*(a++)!=*(b++)) return(25); /* or 42 iyl */ return(0); } void MotorOff(drive) register DrInfo *drive; { drive->Req.io_Command=TD_MOTOR; drive->Req.io_Length=0; DoIO(&drive->Req); } /* * Set present time and date in the creation and last changed field * If the bitmap is -1, it is set to +1. A new checksum is calculated. */ void ChangeRoot(sector) register ULONG *sector; { register ULONG *ptr, sum, i; DateStamp(§or[ROOT_ALTDAYS]); sector[ROOT_CRTDAYS]=sector[ROOT_ALTDAYS]; sector[ROOT_CRTMINS]=sector[ROOT_ALTMINS]; sector[ROOT_CRTTICKS]=sector[ROOT_ALTTICKS]; if (sector[ROOT_BMFFLAG]==-1) sector[ROOT_BMFFLAG]=1; for (ptr=sector,sector[ROOT_CHKSUM]=0,sum=0,i=0;iDevName; strcpy(&Tx0[9],D0->DevName); Tx0[13]=' '; ITDr1.IText=D1->DevName; strcpy(&Tx1[9],D1->DevName); Tx1[13]=' '; error=OpenUser(); if (!(CopyBuffer=(ULONG *)AllocMem(BPCYL,MEMF_CHIP))) ++error; if (!(CompBuffer=(ULONG *)AllocMem(BPCYL,MEMF_CHIP))) ++error; if (!(Hist=(char *)AllocMem(MHIST*MVOLNAME,PUBCLR))) ++error; if (error) Request("Pcopy did not get","enough memory","OK","OK"); return(error); } /* Init() */ /* * Give it all back. */ void Quit() { CloseUser(); if (D0) CloseDrive(D0); if (D1) CloseDrive(D1); if (Hist) FreeMem(Hist,MHIST*MVOLNAME); if (CopyBuffer) FreeMem(CopyBuffer,BPCYL); if (CompBuffer) FreeMem(CompBuffer,BPCYL); if (IntuitionBase) CloseLibrary(IntuitionBase); } /* * Allocate space for the structure, inhibit DOS, setup trackdisk port * and open trackdisk. */ DrInfo *OpenDrive(DrName,Unit) char *DrName; int Unit; { register DrInfo *NewDr=0; if (NewDr=(DrInfo *)AllocMem(sizeof(DrInfo),PUBCLR)){ NewDr->DevName=DrName; NewDr->DOSInhbt=dos_packet(DeviceProc(DrName),ACTION_INHIBIT,DOSTRUE); NewDr->Req.io_Message.mn_Node.ln_Type=NT_MESSAGE; NewDr->Req.io_Message.mn_Node.ln_Pri=0; if (NewDr->Req.io_Message.mn_ReplyPort=CreatePort(0,0)){ if (!(NewDr->Device=OpenDevice(TD_NAME,Unit,&NewDr->Req,1))){ } } } return(NewDr); } /* OpenDrive() */ /* * Close trackdisk device and get rid of memory and ports involved. */ void CloseDrive(drive) register DrInfo *drive; { if (!drive->Device){ MotorOff(drive); CloseDevice(&drive->Req); } if (drive->Req.io_Message.mn_ReplyPort) DeletePort(drive->Req.io_Message.mn_ReplyPort); FreeMem(drive,sizeof(DrInfo)); dos_packet(DeviceProc(drive->DevName),ACTION_INHIBIT,DOSFALSE); } /* CloseDrive */ /* * Check if a start-copy condition occured. If so call the copy routine. */ void CheckCopy() { register DrInfo *Source, *Dest; register short DoCopy; if (D0->Present&&D1->Present){ /* determine direction */ if (ITDr1.FrontPen==DESTCOLOR){ Source=D0; Dest=D1; } else{ Source=D1; Dest=D0; } DoCopy=0; /* three values: FALSE/WAIT/NOWAIT */ if ((GAuto.Flags&SELECTED)&&EnAuto){ if (GUnRd.Flags&SELECTED){ if (!Dest->Readable) DoCopy=NOWAIT; } else if (GNDOS.Flags&SELECTED){ if (!Dest->DOSBoot) DoCopy=NOWAIT; } else DoCopy=(Dest->DOSDisk)?WAIT:NOWAIT; } else if (GCopy.Flags&SELECTED){ GCopy.Flags&=~SELECTED; DrawImage(WS->RPort,&IMBlnk,16,4*GGH); RefOneGadget(&GCopy,WS,0); DoCopy=NOWAIT; } if (DoCopy) DiskCopy(Source,Dest,DoCopy); EnAuto=0; } } /* * Show disk name in Now in .. window, or clear it */ void ShDName(W,text) struct Window *W; register char *text; { static struct IntuiText ITDiskName={ 1,0,JAM2,0,0,0,0,0 }; static struct Image IMDBlank={ 0,0,WD0-4,8,0,0,0,0,0 }; DrawImage(W->RPort,&IMDBlank,2,11); if (text){ if (*text=='\x0e'){ ITDiskName.FrontPen=2; ++text; } else ITDiskName.FrontPen=1; ITDiskName.IText=text; PrintIText(W->RPort,&ITDiskName,12,11); } } /* end of pcopy.c */