/* $Revision Header * Header built automatically - do not edit! ************* * * (C) Copyright 1990 by MXM * * Name .....: Formatter.c * Created ..: Thursday 31-May-90 19:49 * Revision .: 7 * * Date Author Comment * ========= ======== ==================== * 20-Sep-90 Olsen If autostart enabled, displays the * name of the disk inserted. * 29-Aug-90 Olsen Write verification uses blitter * 04-Aug-90 Olsen Sector labels are cleared * 02-Aug-90 Olsen Gadget/menu coordination fixed * 24-Jul-90 Olsen Removed bug in formatting routine, * added disk validation break, * fixed the bootblock checksum * 08-Jul-90 Olsen Sped up the formatting process * 08-Jun-90 Olsen Added the menu * 08-Jun-90 Olsen Fixed some bugs * 31-May-90 Olsen Created this file! * **************************************************************************** * * This file contains the main routines used by Formatter.c * * $Revision Header ********************************************************/ /* Prototypes for this module. */ BYTE FindDevice(char *DevName); VOID RefreshGadget(struct Window *Window,struct Gadget *Gadget,BYTE Colour); VOID ClearPort(VOID); VOID AdjustClass(VOID); VOID ConvertString(char *ToString,char *FromString); ULONG FixBlockSum(ULONG *Array); ULONG FixBootSum(ULONG *Array); VOID SetBitmapBlock(ULONG *BitmapData,SHORT Block,BYTE SetFlag); VOID ClearBlock(ULONG *Block); VOID Inhibit(char *Drive,BYTE Bool); BYTE CompareTracks(ULONG *Track1,ULONG *Track2); BYTE DiskRead(BYTE Track); BYTE DiskWrite(ULONG Offset,BYTE Track); BYTE DiskFormat(BYTE Track); BYTE Formatter(char *DiskName); VOID CentreWindow(struct NewWindow *New,USHORT OffsetX,USHORT OffsetY); VOID DecrementUsage(VOID); VOID CloseAll(BYTE ReturnCode); VOID OpenAll(VOID); LONG Strlen(VOID *String); VOID Strcpy(VOID *Dest,VOID *Source); VOID main(int argc,char **argv); /* Assembly language string routines. */ #pragma regcall(Strlen(a0)) #pragma regcall(Strcpy(a0,a1)) /* Window interaction. */ struct Window *Window; struct IntuiMessage *Massage; ULONG Class,Code; BYTE GadgetID; /* Global information port. */ struct FormatterPort *GlobalPort; #define PORTNAME "Formatter" /* Disk interaction. */ struct MsgPort *DiskPort; struct IOExtTD *DiskRequest; struct MsgPort *TimePort; struct timerequest *TimeRequest; ULONG *DiskTrack,*CheckTrack,*RootTrack,*SectorLabel; BYTE DriveUnit = 0; ULONG OffsetTable[NUMCYLS]; /* Debug flag. */ BYTE DebugFlag = FALSE; /* Boolean flags. */ #define AutoStart (FormatGadget[4] . Flags & SELECTED) #define Verify (FormatGadget[5] . Flags & SELECTED) #define Fast (FormatGadget[6] . Flags & SELECTED) #define Install (FormatGadget[7] . Flags & SELECTED) #define FFS (FormatMenuItem[6].Flags & CHECKED) /* Arp CLI info. */ char *CLI_Template = "Drive,NAME/K,F=FAST/S,I=INSTALL/S,V=VERIFY/S,A=AUTOSTART/S,FFS/S,DEBUG/S"; char *CLI_Help = "\nUsage: Formatter [DF0: | DF1: | DF2: | DF3:] [Name]\n [FAST] [INSTALL] [VERIFY] [AUTOSTART] [FFS]\n"; /* Argument vector offsets. */ #define ARG_DRIVE 1 #define ARG_NAME 2 #define ARG_FAST 3 #define ARG_INSTALL 4 #define ARG_VERIFY 5 #define ARG_AUTOSTART 6 #define ARG_FFS 7 #define ARG_DEBUG 8 /* Drive step delay modification. */ struct FileRequester *DelayFileReq; ULONG OldSteps[4]; /* Offset from window top edge. */ LONG TopEdge; /* Default font for text rendering. */ struct TextAttr DefaultFont = { (STRPTR)"topaz.font", 8, FS_NORMAL, FPF_ROMFONT }; struct TextAttr BoldFont = { (STRPTR)"topaz.font", 8, FSF_BOLD, FPF_ROMFONT }; /* A whole lot of intuition & graphics data. */ struct IntuiText InfoText = { 1,0,JAM1,0,25,&DefaultFont,(UBYTE *)" ",NULL }; struct IntuiText FormatIntTxt[10] = { {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF0:", NULL}, {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF1:", NULL}, {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF2:", NULL}, {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF3:", NULL}, {1,0,0, 20,2,&DefaultFont,(UBYTE *)"Auto start", NULL}, {1,0,0, 12,2,&DefaultFont,(UBYTE *)"Verify Write", NULL}, {1,0,0, 16,2,&DefaultFont,(UBYTE *)"Fast format", NULL}, {1,0,0, 12,2,&DefaultFont,(UBYTE *)"Install Disk", NULL}, {1,0,0, 12,9,&DefaultFont,(UBYTE *)NULL, NULL}, {1,0,0,-48,0,&DefaultFont,(UBYTE *)"Name:", NULL} }; UBYTE FormatText[32],UndoFormatText[32]; struct StringInfo FormatStringInfo = { FormatText,UndoFormatText,0,32,32,0,0,0,0,NULL,NULL,NULL }; SHORT FormatBorderData[] = { -1,-1, 74,-1, 74,12,-1,12,-1,-1, -2,-1, 75,-1, 75,12,-2,12,-2,-1, -1,-1, 74,-1, 74,12,-1,12,-1,-1, -2,-1, 75,-1, 75,12,-2,12,-2,-1, -1,-1, 74,-1, 74,12,-1,12,-1,-1, -2,-1, 75,-1, 75,12,-2,12,-2,-1, -1,-1, 74,-1, 74,12,-1,12,-1,-1, -2,-1, 75,-1, 75,12,-2,12,-2,-1, -1,-1,120,-1,120,12,-1,12,-1,-1, -2,-1,121,-1,121,12,-2,12,-2,-1, -1,-1,120,-1,120,12,-1,12,-1,-1, -2,-1,121,-1,121,12,-2,12,-2,-1, -1,-1,120,-1,120,12,-1,12,-1,-1, -2,-1,121,-1,121,12,-2,12,-2,-1, -1,-1,120,-1,120,12,-1,12,-1,-1, -2,-1,121,-1,121,12,-2,12,-2,-1, -2,-1, 66,-1, 66,27,-2,27,-2,-1, -1,-1, 65,-1, 65,27,-1,27,-1,-1, -1,-1,256,-1,256, 8,-1, 8,-1,-1, -2,-1,257,-1,257, 8,-2, 8,-2,-1 }; struct Border FormatBorder[] = { {0,0,1,0,0,5,&FormatBorderData[ 0],&FormatBorder[ 1]}, {0,0,1,0,0,5,&FormatBorderData[ 10],NULL}, {0,0,1,0,0,5,&FormatBorderData[ 20],&FormatBorder[ 3]}, {0,0,1,0,0,5,&FormatBorderData[ 30],NULL}, {0,0,1,0,0,5,&FormatBorderData[ 40],&FormatBorder[ 5]}, {0,0,1,0,0,5,&FormatBorderData[ 50],NULL}, {0,0,1,0,0,5,&FormatBorderData[ 60],&FormatBorder[ 7]}, {0,0,1,0,0,5,&FormatBorderData[ 70],NULL}, {0,0,1,0,0,5,&FormatBorderData[ 80],&FormatBorder[ 9]}, {0,0,1,0,0,5,&FormatBorderData[ 90],NULL}, {0,0,1,0,0,5,&FormatBorderData[100],&FormatBorder[11]}, {0,0,1,0,0,5,&FormatBorderData[110],NULL}, {0,0,1,0,0,5,&FormatBorderData[120],&FormatBorder[13]}, {0,0,1,0,0,5,&FormatBorderData[130],NULL}, {0,0,1,0,0,5,&FormatBorderData[140],&FormatBorder[15]}, {0,0,1,0,0,5,&FormatBorderData[150],NULL}, {0,0,1,0,0,5,&FormatBorderData[160],&FormatBorder[17]}, {0,0,1,0,0,5,&FormatBorderData[170],NULL}, {0,0,1,0,0,5,&FormatBorderData[180],&FormatBorder[19]}, {0,0,1,0,0,5,&FormatBorderData[190],NULL} }; #define IMMEDIATE (RELVERIFY | GADGIMMEDIATE) #define TOGGLE (RELVERIFY | GADGIMMEDIATE | TOGGLESELECT) struct Gadget FormatGadget[10] = { {&FormatGadget[1], 6,67, 74,12,0,IMMEDIATE, BOOLGADGET, (APTR)&FormatBorder[ 0],NULL,&FormatIntTxt[0],NULL,NULL, 0,NULL}, {&FormatGadget[2], 87,67, 74,12,0,IMMEDIATE, BOOLGADGET, (APTR)&FormatBorder[ 2],NULL,&FormatIntTxt[1],NULL,NULL, 1,NULL}, {&FormatGadget[3],168,67, 74,12,0,IMMEDIATE, BOOLGADGET, (APTR)&FormatBorder[ 4],NULL,&FormatIntTxt[2],NULL,NULL, 2,NULL}, {&FormatGadget[4],249,67, 74,12,0,IMMEDIATE, BOOLGADGET, (APTR)&FormatBorder[ 6],NULL,&FormatIntTxt[3],NULL,NULL, 3,NULL}, {&FormatGadget[5], 6,37,120,12,0,TOGGLE, BOOLGADGET, (APTR)&FormatBorder[ 8],NULL,&FormatIntTxt[4],NULL,NULL, 4,NULL}, {&FormatGadget[6], 6,52,120,12,0,TOGGLE, BOOLGADGET, (APTR)&FormatBorder[10],NULL,&FormatIntTxt[5],NULL,NULL, 5,NULL}, {&FormatGadget[7],132,37,120,12,0,TOGGLE, BOOLGADGET, (APTR)&FormatBorder[12],NULL,&FormatIntTxt[6],NULL,NULL, 6,NULL}, {&FormatGadget[8],132,52,120,12,0,TOGGLE, BOOLGADGET, (APTR)&FormatBorder[14],NULL,&FormatIntTxt[7],NULL,NULL, 7,NULL}, {&FormatGadget[9],258,37, 65,27,0,IMMEDIATE, BOOLGADGET, (APTR)&FormatBorder[16],NULL,&FormatIntTxt[8],NULL,NULL, 8,NULL}, {NULL, 67,82,256, 8,0,IMMEDIATE, STRGADGET, (APTR)&FormatBorder[18],NULL,&FormatIntTxt[9],NULL,(APTR)&FormatStringInfo, 9,NULL} }; UBYTE *FormatInfoText[2] = { (UBYTE *)" Start formatting", (UBYTE *)" Stop formatting" }; struct IntuiText FormatMenuIntTxt[17] = { {0,0,0,0,1,&DefaultFont,(UBYTE *)" About...", NULL}, {0,0,0,0,1,&BoldFont, (UBYTE *)"________________________", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Auto start", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Fast format", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Verify write", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Install disk", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Use FFS", NULL}, {0,0,0,0,1,&BoldFont, (UBYTE *)"________________________", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Drive DF0:", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Drive DF1:", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Drive DF2:", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Drive DF3:", NULL}, {0,0,0,0,1,&BoldFont, (UBYTE *)"________________________", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Modify stepdelay", NULL}, {0,0,0,0,1,&DefaultFont,NULL, NULL}, {0,0,0,0,1,&BoldFont, (UBYTE *)"________________________", NULL}, {0,0,0,0,1,&DefaultFont,(UBYTE *)" Quit", NULL} }; struct MenuItem FormatMenuItem[17] = { {&FormatMenuItem[ 1], 0, 0,192,10, 86,0,(APTR)&FormatMenuIntTxt[ 0],NULL,63,NULL,NULL}, {&FormatMenuItem[ 2], 0, 3,192,10,210,0,(APTR)&FormatMenuIntTxt[ 1],NULL, 0,NULL,NULL}, {&FormatMenuItem[ 3], 0, 13,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 2],NULL,65,NULL,NULL}, {&FormatMenuItem[ 4], 0, 23,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 3],NULL,70,NULL,NULL}, {&FormatMenuItem[ 5], 0, 33,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 4],NULL,86,NULL,NULL}, {&FormatMenuItem[ 6], 0, 43,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 5],NULL,73,NULL,NULL}, {&FormatMenuItem[ 7], 0, 53,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 6],NULL,70,NULL,NULL}, {&FormatMenuItem[ 8], 0, 56,192,10,210,0,(APTR)&FormatMenuIntTxt[ 7],NULL, 0,NULL,NULL}, {&FormatMenuItem[ 9], 0, 66,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 8],NULL,49,NULL,NULL}, {&FormatMenuItem[10], 0, 76,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 9],NULL,50,NULL,NULL}, {&FormatMenuItem[11], 0, 86,192,10, 95,0,(APTR)&FormatMenuIntTxt[10],NULL,51,NULL,NULL}, {&FormatMenuItem[12], 0, 96,192,10, 95,0,(APTR)&FormatMenuIntTxt[11],NULL,52,NULL,NULL}, {&FormatMenuItem[13], 0, 99,192,10,210,0,(APTR)&FormatMenuIntTxt[12],NULL, 0,NULL,NULL}, {&FormatMenuItem[14], 0,109,192,10, 86,0,(APTR)&FormatMenuIntTxt[13],NULL,77,NULL,NULL}, {&FormatMenuItem[15], 0,119,192,10, 86,0,(APTR)&FormatMenuIntTxt[14],NULL,83,NULL,NULL}, {&FormatMenuItem[16], 0,122,192,10,210,0,(APTR)&FormatMenuIntTxt[15],NULL, 0,NULL,NULL}, {NULL, 0,132,192,10, 86,0,(APTR)&FormatMenuIntTxt[16],NULL,81,NULL,NULL} }; struct Menu FormatMenu = {NULL,0,0,112,0,257,"Formatter 2.7",&FormatMenuItem[0]}; struct IntuiText ReqIntTxt[9] = { {2,0,0, 3, 3,&DefaultFont,(UBYTE *)"Copy me, I wish to travel!", NULL}, {2,0,0, 10, 5,&BoldFont, (UBYTE *)"Formatter 2.7", &ReqIntTxt[2]}, {3,0,0,127, 5,&DefaultFont,(UBYTE *)"© Copyright 1990 by MXM", &ReqIntTxt[3]}, {0,0,0,127,17,&DefaultFont,(UBYTE *)"Olaf Barthel", &ReqIntTxt[4]}, {0,0,0,127,25,&DefaultFont,(UBYTE *)"Brabeckstrasse 35", &ReqIntTxt[5]}, {0,0,0,127,33,&DefaultFont,(UBYTE *)"D-3000 Hannover 71", &ReqIntTxt[6]}, {2,0,0, 67,17,&DefaultFont,(UBYTE *)"Author", &ReqIntTxt[7]}, {2,0,0, 11,45,&DefaultFont,(UBYTE *)"Shareware fee", &ReqIntTxt[8]}, {0,0,0,127,45,&DefaultFont,(UBYTE *)"10$ US or DM 15,-", NULL} }; SHORT ReqBorderData[] = { -1,-1,214,-1,214,14,-1,14,-1,-1, -2,-1,215,-1,215,14,-2,14,-2,-1, 0, 0,311, 0,311,75, 0,75, 0, 0, 0, 0,311, 0,311,75, 0,75, 0, 0 }; struct Border ReqBorder[] = { {0,0,2,0,0,5,&ReqBorderData[ 0],&ReqBorder[1]}, {0,0,2,0,0,5,&ReqBorderData[10],NULL}, {4,2,0,0,0,5,&ReqBorderData[20],&ReqBorder[3]}, {5,2,0,0,0,5,&ReqBorderData[30],NULL} }; struct Gadget ReqGadget = {NULL,53,58,214,14,0,3,4097,(APTR)&ReqBorder[0],NULL,&ReqIntTxt[0],NULL,NULL,0,NULL}; struct Requester Req; struct IntuiText DelayIntTxt[9] = { {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF0:", NULL}, {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF1:", NULL}, {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF2:", NULL}, {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF3:", NULL}, {2,1,0, 8, 5,&DefaultFont,(UBYTE *)"Load settings", NULL}, {2,1,0, 8, 5,&DefaultFont,(UBYTE *)"Save settings", NULL}, {2,1,0, 36, 3,&DefaultFont,(UBYTE *)"Accept", NULL}, {2,1,0, 36, 3,&DefaultFont,(UBYTE *)"Cancel", NULL}, {2,1,0, 13,50,&DefaultFont,(UBYTE *)"The default drive step delay is 3000.", NULL} }; UBYTE DelayString0[11]; UBYTE UndoDelayString0[11]; UBYTE DelayString1[11]; UBYTE UndoDelayString1[11]; UBYTE DelayString2[11]; UBYTE UndoDelayString2[11]; UBYTE DelayString3[11]; UBYTE UndoDelayString3[11]; struct StringInfo DelayStringInfo[4] = { {DelayString0,UndoDelayString0,1,11,11,0,0,0,0,NULL,NULL,NULL}, {DelayString1,UndoDelayString1,1,11,11,0,0,0,0,NULL,NULL,NULL}, {DelayString2,UndoDelayString2,1,11,11,0,0,0,0,NULL,NULL,NULL}, {DelayString3,UndoDelayString3,1,11,11,0,0,0,0,NULL,NULL,NULL} }; SHORT DelayBorderData[] = { -1,-1, 88,-1, 88, 8,-1, 8,-1,-1, -2,-1, 89,-1, 89, 8,-2, 8,-2,-1, -1,-1, 88,-1, 88, 8,-1, 8,-1,-1, -2,-1, 89,-1, 89, 8,-2, 8,-2,-1, -1,-1, 88,-1, 88, 8,-1, 8,-1,-1, -2,-1, 89,-1, 89, 8,-2, 8,-2,-1, -1,-1, 88,-1, 88, 8,-1, 8,-1,-1, -2,-1, 89,-1, 89, 8,-2, 8,-2,-1, -1,-1,120,-1,120,19,-1,19,-1,-1, -2,-1,121,-1,121,19,-2,19,-2,-1, 1, 1,118, 1,118,17, 1,17, 1, 1, 2, 1,117, 1,117,17, 2,17, 2, 1, -1,-1,120,-1,120,19,-1,19,-1,-1, -2,-1,121,-1,121,19,-2,19,-2,-1, 1, 1,118, 1,118,17, 1,17, 1, 1, 2, 1,117, 1,117,17, 2,17, 2, 1, -1,-1,120,-1,120,14,-1,14,-1,-1, -2,-1,121,-1,121,14,-2,14,-2,-1, 1, 1,118, 1,118,12, 1,12, 1, 1, 2, 1,117, 1,117,12, 2,12, 2, 1, -1,-1,120,-1,120,14,-1,14,-1,-1, -2,-1,121,-1,121,14,-2,14,-2,-1, 1, 1,118, 1,118,12, 1,12, 1, 1, 2, 1,117, 1,117,12, 2,12, 2, 1, 0, 0,318, 0,318,77, 0,77, 0, 1, 0, 0,318, 0,318,77, 0,77, 0, 1 }; struct Border DelayBorder[26] = { {0,0,2,0,0,5,&DelayBorderData[ 0],&DelayBorder[ 1]}, {0,0,2,0,0,5,&DelayBorderData[ 10],NULL}, {0,0,2,0,0,5,&DelayBorderData[ 20],&DelayBorder[ 3]}, {0,0,2,0,0,5,&DelayBorderData[ 30],NULL}, {0,0,2,0,0,5,&DelayBorderData[ 40],&DelayBorder[ 5]}, {0,0,2,0,0,5,&DelayBorderData[ 50],NULL}, {0,0,2,0,0,5,&DelayBorderData[ 60],&DelayBorder[ 7]}, {0,0,2,0,0,5,&DelayBorderData[ 70],NULL}, {0,0,2,0,0,5,&DelayBorderData[ 80],&DelayBorder[ 9]}, {0,0,2,0,0,5,&DelayBorderData[ 90],&DelayBorder[10]}, {0,0,2,0,0,5,&DelayBorderData[100],&DelayBorder[11]}, {0,0,2,0,0,5,&DelayBorderData[110],NULL}, {0,0,2,0,0,5,&DelayBorderData[120],&DelayBorder[13]}, {0,0,2,0,0,5,&DelayBorderData[130],&DelayBorder[14]}, {0,0,2,0,0,5,&DelayBorderData[140],&DelayBorder[15]}, {0,0,2,0,0,5,&DelayBorderData[150],NULL}, {0,0,2,0,0,5,&DelayBorderData[160],&DelayBorder[17]}, {0,0,2,0,0,5,&DelayBorderData[170],&DelayBorder[18]}, {0,0,2,0,0,5,&DelayBorderData[180],&DelayBorder[19]}, {0,0,2,0,0,5,&DelayBorderData[190],NULL}, {0,0,2,0,0,5,&DelayBorderData[200],&DelayBorder[21]}, {0,0,2,0,0,5,&DelayBorderData[210],&DelayBorder[22]}, {0,0,2,0,0,5,&DelayBorderData[220],&DelayBorder[23]}, {0,0,2,0,0,5,&DelayBorderData[230],NULL}, {2,1,2,0,0,5,&DelayBorderData[240],&DelayBorder[25]}, {3,1,2,0,0,5,&DelayBorderData[250],NULL} }; struct Gadget DelayGadgets[8] = { {&DelayGadgets[1], 101, 5, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 0],NULL,(APTR)&DelayIntTxt[0],NULL,(APTR)&DelayStringInfo[0], 0,NULL}, {&DelayGadgets[2], 101,16, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 2],NULL,(APTR)&DelayIntTxt[1],NULL,(APTR)&DelayStringInfo[1], 1,NULL}, {&DelayGadgets[3], 101,27, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 4],NULL,(APTR)&DelayIntTxt[2],NULL,(APTR)&DelayStringInfo[2], 2,NULL}, {&DelayGadgets[4], 101,38, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 6],NULL,(APTR)&DelayIntTxt[3],NULL,(APTR)&DelayStringInfo[3], 3,NULL}, {&DelayGadgets[5], 195, 5,120,19,0, 3,4097,(APTR)&DelayBorder[ 8],NULL,(APTR)&DelayIntTxt[4],NULL,NULL, 4,NULL}, {&DelayGadgets[6], 195,27,120,19,0, 3,4097,(APTR)&DelayBorder[12],NULL,(APTR)&DelayIntTxt[5],NULL,NULL, 5,NULL}, {&DelayGadgets[7], 12,61,120,14,0, 3,4097,(APTR)&DelayBorder[16],NULL,(APTR)&DelayIntTxt[6],NULL,NULL, 6,NULL}, {NULL, 195,61,120,14,0, 3,4097,(APTR)&DelayBorder[20],NULL,(APTR)&DelayIntTxt[7],NULL,NULL, 7,NULL} }; struct Requester DelayReq; /* A very new window (well, sort of). */ struct NewWindow NewWindow = { 0,0, 330,93, -1,-1, CLOSEWINDOW | GADGETUP | MOUSEBUTTONS | MENUPICK | VANILLAKEY, WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | ACTIVATE | RMBTRAP, (struct Gadget *)&FormatGadget[0], (struct Image *)NULL, (STRPTR)"Formatter 2.7", (struct Screen *)NULL, (struct BitMap *)NULL, 0,0, 0,0, WBENCHSCREEN }; /* The track indicator (run dump). */ USHORT PanelMap[220] = { 0x78F0,0x0000,0x0030,0xF000,0x0000,0x78F0,0x0000,0x0078, 0xF000,0x0000,0xC0F0,0x0000,0x00FC,0xF000,0x0000,0x78F0, 0x0000,0x00FC,0xF000,0x0000,0xCD98,0x0000,0x0071,0x9800, 0x0000,0xCD98,0x0000,0x00CD,0x9800,0x0000,0xD998,0x0000, 0x00C1,0x9800,0x0000,0xC198,0x0000,0x000D,0x9800,0x0000, 0xCD98,0x0000,0x0031,0x9800,0x0000,0x1998,0x0000,0x0019, 0x9800,0x0000,0xD998,0x0000,0x00F9,0x9800,0x0000,0xF998, 0x0000,0x0019,0x9800,0x0000,0xCD98,0x0000,0x0031,0x9800, 0x0000,0x3198,0x0000,0x00CD,0x9800,0x0000,0xFD98,0x0000, 0x000D,0x9800,0x0000,0xCD98,0x0000,0x0031,0x9800,0x0000, 0x78F0,0x0000,0x0078,0xF000,0x0000,0xFCF0,0x0000,0x0078, 0xF000,0x0000,0x18F0,0x0000,0x00F8,0xF000,0x0000,0x78F0, 0x0000,0x0030,0xF000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, 0xC000,0x0000,0x00C0,0x0000,0x0000,0xC000,0x0000,0x00C0, 0x0000,0x0000,0xC000,0x0000,0x00C0,0x0000,0x0000,0xC000, 0x0000,0x00C0,0x0000,0x0000,0xC000,0x0000,0x00C0,0x0000, 0x0000,0xC000,0x0000,0x00C0,0x0000,0x0000,0xC000,0x0000, 0x00C0,0x0000,0x0000,0xC000,0x0000,0x00C0,0x0000,0x0000, 0xC000,0x0C00,0x00C0,0x000C,0x0000,0xC000,0x0C00,0x00C0, 0x000C,0x0000,0xC000,0x0C00,0x00C0,0x000C,0x0000,0xC000, 0x0C00,0x00C0,0x000C,0x0000,0xC000,0x0C00,0x00C0,0x000C, 0x0000,0xC000,0x0C00,0x00C0,0x000C,0x0000,0xC000,0x0C00, 0x00C0,0x000C,0x0000,0xC000,0x0C00,0x00C0,0x000C,0x0000, 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, 0xFFFF,0xFFFF,0xFFFF,0xFFFF }; /* The track indicator (the image structure). */ struct Image PanelImage = { 0,0, 320,11,1, (USHORT *)&PanelMap[0], 0x01,0x00, (struct Image *)NULL }; /* A rectangular shape. */ struct Image Box = { 0,0,4,12,2, (USHORT *)NULL, 0,0x03, (struct Image *)NULL }; /* A standard disk bootblock (as used by the install command, only the * DOS disk ID and the checksum are missing). */ ULONG Standard[13] = { 0x00000000,0x00000000,0x00000370,0x43FA0018,0x4EAEFFA0,0x4A80670A, 0x20402068,0x00167000,0x4E7570FF,0x60FA646F,0x732E6C69,0x62726172, 0x79000000 }; /* Some embedded assembly language code. */ #asm PUBLIC _Strlen PUBLIC _Strcpy ; Simple strlen routine. _Strlen: MOVEQ #0,D0 ; Reset length counter 1$ TST.B (A0)+ ; Check for end BEQ.S 2$ ; Found it ADDQ #1,D0 ; Increment length counter BRA.S 1$ ; Test again 2$ RTS ; Simple strcpy routine _Strcpy: TST.B (A1) ; Check source byte BEQ.S 1$ ; Found the end? MOVE.B (A1)+,(A0)+ ; Copy the byte over BRA.S _Strcpy ; Test again 1$ MOVE.B #0,(A0) ; Null termination RTS #endasm /* FindDevice(): * * Tries to discover a device name in the linked list * of device nodes to be found in DosLibrary. */ BYTE FindDevice(char *DevName) { extern struct DosLibrary *DOSBase; char *Pointer,Name[257]; register struct DeviceNode *DevInfo; struct RootNode *RootNode = (struct RootNode *)DOSBase -> dl_Root; SHORT i; /* Knock the rest of the system out. */ Forbid(); /* The starting point. */ DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(RootNode -> rn_Info)) -> di_DevInfo); /* As long as it's valid. */ while(DevInfo) { /* Is it a device and does it have a file handler task attached? */ if(DevInfo -> dn_Type == DLT_DEVICE && DevInfo -> dn_Task) { /* Convert the name. */ Pointer = (char *)BADDR(DevInfo -> dn_Name); for(i = 0 ; i < Pointer[0] ; i++) Name[i] = Pointer[i + 1]; Name[Pointer[0] ] = ':'; Name[Pointer[0] + 1] = 0; /* Compare the names. */ if(!Strcmp(Name,DevName)) { Permit(); return(TRUE); } } /* Check next entry. */ DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next); } Permit(); return(FALSE); } /* RefreshGadget(): * * Clears the background of a gadget and refreshes it. */ VOID RefreshGadget(struct Window *Window,struct Gadget *Gadget,BYTE Colour) { struct Gadget *NextGadget = Gadget -> NextGadget; BYTE FgPen = Window -> RPort -> FgPen; /* Clear the background. */ SetAPen(Window -> RPort,Colour); RectFill(Window -> RPort,Gadget -> LeftEdge,Gadget -> TopEdge,Gadget -> LeftEdge + Gadget -> Width - 1,Gadget -> TopEdge + Gadget -> Height - 1); SetAPen(Window -> RPort,FgPen); /* Refresh a single gadget. */ Gadget -> NextGadget = NULL; RefreshGadgets(Gadget,Window,NULL); Gadget -> NextGadget = NextGadget; } /* ClearPort(): * * Removes all pending messages from the Window UserPort. */ VOID ClearPort() { while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) ReplyMsg(Massage); Class = NULL; Code = NULL; } /* PerformRequest(): * * Display the information requester in the * formatter window. */ VOID PerformRequest() { InitRequester(&Req); /* I don't know how it happened, but the main * window is an odd number of rows wide, which * makes it somehow difficult to cover the * window properly with the requester. */ Req . LeftEdge = 4; Req . TopEdge = 11 + TopEdge; Req . Width = 324; Req . Height = 80; Req . BackFill = 1; Req . Flags = NOISYREQ | SIMPLEREQ; Req . ReqGadget = &ReqGadget; Req . ReqBorder = &ReqBorder[2]; Req . ReqText = &ReqIntTxt[1]; /* Now, this gets really boring. */ if(Request(&Req,Window)) { FOREVER { WaitPort(Window -> UserPort); while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; if(Class == GADGETUP || Class == VANILLAKEY) { EndRequest(&Req,Window); return; } } } } } /* SetStepDelays(): * * Adjusts the step delay for all four disk drives. */ VOID SetStepDelays(ULONG *DelayTable) { struct MsgPort *DelayPort; struct IOExtTD *TDDelayRequest; struct TDU_PublicUnit *PublicUnit; SHORT i; if(DelayPort = (struct MsgPort *)CreatePort(NULL,0)) { if(TDDelayRequest = (struct IOExtTD *)CreateExtIO(DelayPort,sizeof(struct IOExtTD))) { Forbid(); for(i = 0 ; i < 4 ; i++) { if(DelayTable[i]) { if(!OpenDevice(TD_NAME,i,TDDelayRequest,0)) { PublicUnit = (struct TDU_PublicUnit *)TDDelayRequest -> iotd_Req . io_Unit; PublicUnit -> tdu_StepDelay = DelayTable[i]; CloseDevice(TDDelayRequest); } } } Permit(); for(i = 0 ; i < 4 ; i++) DelayStringInfo[i] . LongInt = DelayTable[i]; SPrintf((char *)DelayString0,"%ld",DelayStringInfo[0] . LongInt); SPrintf((char *)DelayString1,"%ld",DelayStringInfo[1] . LongInt); SPrintf((char *)DelayString2,"%ld",DelayStringInfo[2] . LongInt); SPrintf((char *)DelayString3,"%ld",DelayStringInfo[3] . LongInt); Strcpy(UndoDelayString0,DelayString0); Strcpy(UndoDelayString1,DelayString1); Strcpy(UndoDelayString2,DelayString2); Strcpy(UndoDelayString3,DelayString3); DeleteExtIO(TDDelayRequest); } DeletePort(DelayPort); } } /* PerformDelayRequest(): * * This requester helps the user to adjust the step * delay of all four disk drives. */ VOID PerformDelayRequest() { SHORT i; USHORT ID; ULONG DelayTable[4],OldDelayTable[4]; for(i = 0 ; i < 4 ; i++) OldDelayTable[i] = DelayStringInfo[i] . LongInt; InitRequester(&DelayReq); /* I don't know how it happened, but the main * window is an odd number of rows wide, which * makes it somehow difficult to cover the * window properly with the requester. */ DelayReq . LeftEdge = 4; DelayReq . TopEdge = 11 + TopEdge; DelayReq . Width = 324; DelayReq . Height = 80; DelayReq . BackFill = 1; DelayReq . Flags = SIMPLEREQ; DelayReq . ReqGadget = &DelayGadgets[0]; DelayReq . ReqBorder = &DelayBorder[24]; DelayReq . ReqText = &DelayIntTxt[8]; /* Now, this gets really boring. */ if(Request(&DelayReq,Window)) { FOREVER { WaitPort(Window -> UserPort); while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; ID = ((struct Gadget *)Massage -> IAddress) -> GadgetID; if(Class == GADGETUP) { switch(ID) { /* Drives. */ case 0: case 1: case 2: case 3: break; /* Load settings. */ case 4: if(!DelayFileReq) { if(DelayFileReq = ArpAllocFreq()) { Strcpy(DelayFileReq -> fr_File,"Formatter_Steps"); Strcpy(DelayFileReq -> fr_Dir,"S:"); } } if(DelayFileReq) { DelayFileReq -> fr_Hail = "Load settings"; while(FileRequest(DelayFileReq)) { BPTR Handle; char Name[DSIZE * 5 + FCHARS]; ULONG TempDelay[4]; Strcpy(Name,DelayFileReq -> fr_Dir); TackOn(Name,DelayFileReq -> fr_File); if(Handle = Open(Name,MODE_OLDFILE)) { if(Read(Handle,TempDelay,4 * sizeof(ULONG)) == 4 * sizeof(ULONG)) { for(i = 0 ; i < 4 ; i++) DelayStringInfo[i] . LongInt = TempDelay[i]; SPrintf((char *)DelayString0,"%ld",DelayStringInfo[0] . LongInt); SPrintf((char *)DelayString1,"%ld",DelayStringInfo[1] . LongInt); SPrintf((char *)DelayString2,"%ld",DelayStringInfo[2] . LongInt); SPrintf((char *)DelayString3,"%ld",DelayStringInfo[3] . LongInt); Strcpy(UndoDelayString0,DelayString0); Strcpy(UndoDelayString1,DelayString1); Strcpy(UndoDelayString2,DelayString2); Strcpy(UndoDelayString3,DelayString3); RefreshGadgets(&DelayGadgets[0],Window,&DelayReq); Close(Handle); break; } Close(Handle); } DisplayBeep(Window -> WScreen); } } break; /* Save settings. */ case 5: if(!DelayFileReq) { if(DelayFileReq = ArpAllocFreq()) { Strcpy(DelayFileReq -> fr_File,"Formatter_Steps"); Strcpy(DelayFileReq -> fr_Dir,"S:"); } } if(DelayFileReq) { ULONG TempDelay[4]; DelayFileReq -> fr_Hail = "Save settings"; for(i = 0 ; i < 4 ; i++) TempDelay[i] = DelayStringInfo[i] . LongInt; while(FileRequest(DelayFileReq)) { BPTR Handle; char Name[DSIZE * 5 + FCHARS]; Strcpy(Name,DelayFileReq -> fr_Dir); TackOn(Name,DelayFileReq -> fr_File); if(Handle = Open(Name,MODE_NEWFILE)) { if(Write(Handle,TempDelay,4 * sizeof(ULONG)) == 4 * sizeof(ULONG)) { Close(Handle); break; } Close(Handle); } DisplayBeep(Window -> WScreen); } } break; /* Accept. */ case 6: for(i = 0 ; i < 4 ; i++) DelayTable[i] = DelayStringInfo[i] . LongInt; SetStepDelays(DelayTable); EndRequest(&DelayReq,Window); return; /* Cancel. */ case 7: EndRequest(&DelayReq,Window); SetStepDelays(OldDelayTable); return; } } } } } } /* AdjustClass(): * * Formatter is controlled both by menu and by gadgets; * the following routine links both interfaces. */ VOID AdjustClass() { USHORT MenuNum = Code; /* Truly selected a menu item? */ if(MenuNum != MENUNULL) { BYTE i; Class = GADGETUP; /* Get the menu item behind the Intuition menu number. */ while(MenuNum != MENUNULL) { if(MENUNUM(MenuNum) == 0) { switch(ITEMNUM(MenuNum)) { case 0: PerformRequest(); Class = NULL; break; case 2: FormatGadget[4] . Flags ^= SELECTED; RefreshGadget(Window,&FormatGadget[4],0); Class = NULL; break; case 3: FormatGadget[6] . Flags ^= SELECTED; RefreshGadget(Window,&FormatGadget[6],0); Class = NULL; break; case 4: FormatGadget[5] . Flags ^= SELECTED; RefreshGadget(Window,&FormatGadget[5],0); Class = NULL; break; case 5: FormatGadget[7] . Flags ^= SELECTED; RefreshGadget(Window,&FormatGadget[7],0); Class = NULL; break; case 8: case 9: case 10: case 11:for(i = 0 ; i < 4 ; i++) if((FormatMenuItem[8 + i] . Flags & ITEMENABLED) && 8 + i != ITEMNUM(MenuNum)) FormatMenuItem[8 + i] . Flags &= ~CHECKED; GadgetID = ITEMNUM(MenuNum) - 8; break; case 13:PerformDelayRequest(); Class = NULL; break; case 14:GadgetID = 8; break; case 16:Class = CLOSEWINDOW; break; default:Class = NULL; break; } } MenuNum = ((struct MenuItem *)ItemAddress(&FormatMenu,MenuNum)) -> NextSelect; } } } /* ConvertString(): * * Turn a 'C' string into a BCPL string. */ VOID ConvertString(char *ToString,char *FromString) { *ToString++ = Strlen(FromString); while(*FromString) *ToString++ = *FromString++; } /* FixBlockSum(): * * Calculate the checksum for a DOS disk block. * The checksum itself is the complement of the sum * of all the longwords contained in a track. */ ULONG FixBlockSum(ULONG *Array) { ULONG Sum = 0; UBYTE i = 128; while(i--) Sum += Array[i]; return(-Sum); } /* FixBootSum(ULONG *Array): * * Calculates the checksum for a disk bootblock, which * unfortunately uses an algorithm different from * FixBlockSum. */ ULONG FixBootSum(ULONG *Array) { ULONG Sum = 0,LastSum; UBYTE i = 128; while(i--) { LastSum = Sum; if((Sum += Array[i]) < LastSum) Sum++; } return(~Sum); } /* SetBitmapBlock(): * * Marks a block in the disk bitmap (bit by bit). * A standard bitmap consists of fifty-five longwords * in which each bit represents a disk block. If a * bit is set, a block is unused. A cleared bit indicates * an allocated block. */ VOID SetBitmapBlock(ULONG *BitmapData,SHORT Block,BYTE SetFlag) { if(SetFlag) BitmapData[Block / 32] &= ~(1 << (Block % 32)); else BitmapData[Block / 32] |= (1 << (Block % 32)); } /* ClearBlock(): * * Set the contents of disk block to zero. It takes less * time to clear the longwords contained in a disk track * than to clear the single bytes. */ VOID ClearBlock(ULONG *Block) { UBYTE Offset = 128; while(Offset--) *Block++ = 0; } /* Inhibit(): * * Toggle the activity of the disk validator. We send * a DOS packet to the file handler task telling it * to disable or to enable the disk validator. */ VOID Inhibit(char *Drive,BYTE Bool) { struct MsgPort *Handler; LONG Args[7]; if(Bool) Args[0] = DOSTRUE; else Args[0] = DOSFALSE; if(Handler = DeviceProc(Drive)) SendPacket(ACTION_INHIBIT,Args,Handler); } /* CompareTracks(): * * Check if two disk blocks are equal. */ BYTE CompareTracks(ULONG *Track1,ULONG *Track2) { BYTE Result; /* Allocate the blitter for private use. */ OwnBlitter(); WaitBlit(); /* Set the blitter data addresses. We will use * sources A & C. */ custom . bltapt = (APTR)Track1; custom . bltcpt = (APTR)Track2; /* The blitter modulo values are not important * in this example. */ custom . bltamod = 0; custom . bltcmod = 0; /* Set the first and last word mask values. */ custom . bltafwm = 0xFFFF; custom . bltalwm = 0xFFFF; /* Set the blitter control registers. * We will work with sources A & C. The * minterm A_XOR_C will cause the blitter to * generate zeroes if both sources are * equal. */ custom . bltcon0 = SRCA | SRCC | A_XOR_C; custom . bltcon1 = 0; /* This last assignment starts the blitter. * The size of a disk track is 11264 bytes, * in other words, 64 x 176 bytes. */ /* custom . bltsize = (((176 & VSIZEMASK) << 6 ) | ((64 >> 1) & HSIZEMASK));*/ custom . bltsize = 0x2C20; WaitBlit(); /* If both sources are equal zeroes will have * been generated, i.e. the blitter zero * flag will be set. */ if(custom . dmaconr & DMAF_BLTNZERO) Result = TRUE; else Result = FALSE; DisownBlitter(); return(Result); } /* DiskRead(): * * Read a track from disk and compare it with the * data in the buffer. */ BYTE DiskRead(BYTE Track) { SHORT Position = 4 + Box . Width * Track; BYTE Error; /* Initialize the request. */ DiskRequest -> iotd_Req . io_Offset = OffsetTable[Track]; /* Start the request. */ BeginIO(DiskRequest); /* Move up one track. */ Box . PlaneOnOff = 3; DrawImage(Window -> RPort,&Box,Position,23 + TopEdge); /* News in the mail? */ if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; GadgetID = ((struct Gadget *)Massage -> IAddress) -> GadgetID; ReplyMsg(Massage); if(Class == MENUPICK) AdjustClass(); if(Class == GADGETUP) { /* Stop formatting? */ if(GadgetID == 8) { /* Wait for request to be replied. */ WaitIO(DiskRequest); /* Format aborted. */ return(-42); } if(GadgetID == 4) FormatMenuItem[2] . Flags ^= CHECKED; if(GadgetID == 6) FormatMenuItem[3] . Flags ^= CHECKED; if(GadgetID == 5) FormatMenuItem[4] . Flags ^= CHECKED; if(GadgetID == 7) FormatMenuItem[5] . Flags ^= CHECKED; } } /* Trouble? */ if(Error = WaitIO(DiskRequest)) return(Error); /* Are both buffers equal? */ if(Track == 40) { if(!CompareTracks(DiskTrack,RootTrack)) { Box . PlaneOnOff = 2; DrawImage(Window -> RPort,&Box,Position,23 + TopEdge); if(DebugFlag) { char HelpName[20]; BPTR Help; SPrintf(HelpName,"RAM:SRCTRACK%02ld",Track); if(Help = Open(HelpName,MODE_NEWFILE)) { Write(Help,RootTrack,NUMSECS * NUMHEADS * TD_SECTOR); Close(Help); } SPrintf(HelpName,"RAM:DSTTRACK%02ld",Track); if(Help = Open(HelpName,MODE_NEWFILE)) { Write(Help,DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR); Close(Help); } } /* Verification error. */ return(-43); } } else { if(!CompareTracks(DiskTrack,CheckTrack)) { Box . PlaneOnOff = 2; DrawImage(Window -> RPort,&Box,Position,23 + TopEdge); /* Verification error. */ if(DebugFlag) { char HelpName[20]; BPTR Help; SPrintf(HelpName,"RAM:SRCTRACK%02ld",Track); if(Help = Open(HelpName,MODE_NEWFILE)) { Write(Help,CheckTrack,NUMSECS * NUMHEADS * TD_SECTOR); Close(Help); } SPrintf(HelpName,"RAM:DSTTRACK%02ld",Track); if(Help = Open(HelpName,MODE_NEWFILE)) { Write(Help,DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR); Close(Help); } } return(-43); } } return(0); } /* DiskWrite(): * * Write two blocks to disk. */ BYTE DiskWrite(ULONG Offset,BYTE Track) { SHORT Position = 4 + Box . Width * Track; ULONG *OriginalTrack = DiskRequest -> iotd_Req . io_Data; BYTE Error; /* Initialize the request. */ DiskRequest -> iotd_Req . io_Command = ETD_WRITE; DiskRequest -> iotd_Req . io_Length = TD_SECTOR * 2; DiskRequest -> iotd_Req . io_Offset = Offset; /* Start the request. */ BeginIO(DiskRequest); /* Move up one track. */ Box . PlaneOnOff = 1; DrawImage(Window -> RPort,&Box,Position,23 + TopEdge); /* News in the mail? */ if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; GadgetID = ((struct Gadget *)Massage -> IAddress) -> GadgetID; ReplyMsg(Massage); if(Class == MENUPICK) AdjustClass(); if(Class == GADGETUP) { /* Stop formatting? */ if(GadgetID == 8) { /* Wait for request to be replied. */ WaitIO(DiskRequest); /* Format aborted. */ return(-42); } if(GadgetID == 4) FormatMenuItem[2] . Flags ^= CHECKED; if(GadgetID == 6) FormatMenuItem[3] . Flags ^= CHECKED; if(GadgetID == 5) FormatMenuItem[4] . Flags ^= CHECKED; if(GadgetID == 7) FormatMenuItem[5] . Flags ^= CHECKED; } } /* Trouble? */ if(Error = WaitIO(DiskRequest)) return(Error); /* Verify the data? */ if(Verify) { /* Make sure the buffer has been written. */ DiskRequest -> iotd_Req . io_Command = ETD_UPDATE; DoIO(DiskRequest); /* Reread the buffer. */ DiskRequest -> iotd_Req . io_Command = ETD_READ; DiskRequest -> iotd_Req . io_Data = (APTR)CheckTrack; if(Error = DoIO(DiskRequest)) return(Error); /* Are both buffers equal? */ if(!CompareTracks(OriginalTrack,CheckTrack)) { Box . PlaneOnOff = 2; DrawImage(Window -> RPort,&Box,Position,23 + TopEdge); /* Verification error. */ return(-43); } Box . PlaneOnOff = 3; DrawImage(Window -> RPort,&Box,Position,23 + TopEdge); } return(0); } /* DiskFormat(): * * Perform a disk write access. */ BYTE DiskFormat(BYTE Track) { BYTE Error; /* Initialize the request. */ DiskRequest -> iotd_Req . io_Offset = OffsetTable[Track]; /* Install the sector label information. */ DiskRequest -> iotd_SecLabel = (ULONG)SectorLabel; if(Track == 40) DiskRequest -> iotd_Req . io_Data = (APTR)RootTrack; /* Start the request. */ BeginIO(DiskRequest); /* Move up one track. */ Box . PlaneOnOff = 1; DrawImage(Window -> RPort,&Box,4 + Box . Width * Track,23 + TopEdge); /* News in the mail? */ if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; GadgetID = ((struct Gadget *)Massage -> IAddress) -> GadgetID; ReplyMsg(Massage); if(Class == MENUPICK) AdjustClass(); if(Class == GADGETUP) { /* Stop formatting? */ if(GadgetID == 8) { /* Wait for request to be replied. */ WaitIO(DiskRequest); if(Track == 40) DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack; /* Format aborted. */ DiskRequest -> iotd_SecLabel = NULL; return(-42); } if(GadgetID == 4) FormatMenuItem[2] . Flags ^= CHECKED; if(GadgetID == 6) FormatMenuItem[3] . Flags ^= CHECKED; if(GadgetID == 5) FormatMenuItem[4] . Flags ^= CHECKED; if(GadgetID == 7) FormatMenuItem[5] . Flags ^= CHECKED; } } Error = WaitIO(DiskRequest); if(Track == 40) DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack; DiskRequest -> iotd_SecLabel = NULL; return(Error); } /* Formatter(): * * Format a disk drive, 3½" hardwired to the Amiga. */ BYTE Formatter(char *DiskName) { struct DosDirectory *RootBlock; struct DosBitmap *DosBitmap; BYTE Error,GeneralError = FALSE; SHORT i,Count = 0; /* Allocate both auxilary buffers. */ if(CheckTrack = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_SECTOR,MEMF_CHIP | MEMF_CLEAR)) { if(DiskTrack = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_SECTOR,MEMF_CHIP | MEMF_CLEAR)) { if(RootTrack = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_SECTOR,MEMF_CHIP | MEMF_CLEAR)) { if(SectorLabel = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_LABELSIZE,MEMF_CHIP | MEMF_CLEAR)) { /* It's a DOS disk. */ if(FFS) CheckTrack[0] = DiskTrack[0] = ID_FFS_DISK; else CheckTrack[0] = DiskTrack[0] = ID_DOS_DISK; /* Tie them to the buffer. */ RootBlock = (struct DosDirectory *)RootTrack; DosBitmap = (struct DosBitmap *)((ULONG)RootTrack + TD_SECTOR); /* Clear the root block. */ ClearBlock((ULONG *)RootBlock); /* Initialize the defaults. */ RootBlock -> PrimaryType = T_SHORT; RootBlock -> SecondaryType = ST_ROOT; RootBlock -> HashTableSize = 128 - 56; RootBlock -> BitmapFlag = DOSFALSE; RootBlock -> BitmapPointers[0] = (NUMTRACKS / 2) * NUMSECS + 1; /* Set the date stamps. */ DateStamp(&RootBlock -> LastRootChange); DateStamp(&RootBlock -> LastDiskChange); DateStamp(&RootBlock -> CreationDate); /* Copy the name string over. */ ConvertString(RootBlock -> DiskName,DiskName); /* Calculate the block checksum. */ RootBlock -> CheckSum = FixBlockSum((ULONG *)RootBlock); /* Clear the disk bitmap. */ ClearBlock((ULONG *)DosBitmap); /* Mark all bitmap blocks as unused. */ for(i = 0 ; i < 55 ; i++) DosBitmap -> BitmapData[i] = ~0L; /* Mark two blocks as used (880 -> Root block, 881 -> Bitmap). * Note that the first two blocks by default are reserved * and, not being part of the bitmap itself, have to * be skipped. */ SetBitmapBlock(DosBitmap -> BitmapData,880 - 2,TRUE); SetBitmapBlock(DosBitmap -> BitmapData,881 - 2,TRUE); /* Calculate the block checksum. */ DosBitmap -> CheckSum = FixBlockSum((ULONG *)DosBitmap); /* Is there a disk in the drive? */ DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE; DoIO(DiskRequest); if(!DiskRequest -> iotd_Req . io_Actual) { /* Is the disk write enabled? */ DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS; DoIO(DiskRequest); if(!DiskRequest -> iotd_Req . io_Actual) { /* Get the disk change number. */ DiskRequest -> iotd_Req . io_Command = TD_CHANGENUM; DoIO(DiskRequest); /* Set the standard flags. */ DiskRequest -> iotd_Req . io_Flags = 0; DiskRequest -> iotd_Count = DiskRequest -> iotd_Req . io_Actual; /* Remove all messages. */ ClearPort(); if(AutoStart) { DiskRequest -> iotd_Req . io_Command = ETD_READ; DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack; DiskRequest -> iotd_Req . io_Length = NUMSECS * NUMHEADS * TD_SECTOR; DiskRequest -> iotd_Req . io_Offset = OffsetTable[40]; if(!DoIO(DiskRequest)) { if(!FixBlockSum((ULONG *)DiskTrack)) { CopyMem(&((struct DosDirectory *)DiskTrack) -> DiskName[1],InfoText . IText,32); InfoText . IText[((struct DosDirectory *)DiskTrack) -> DiskName[0]] = 0; InfoText . LeftEdge = 4 + (320 - 8 * Strlen(InfoText . IText)) / 2; InfoText . FrontPen = 3; PrintIText(Window -> RPort,&InfoText,0,TopEdge); InfoText . FrontPen = 1; DisplayBeep(Window -> WScreen); FOREVER { if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; GadgetID = ((struct Gadget *)Massage -> IAddress) -> GadgetID; ReplyMsg(Massage); if(Class == MENUPICK) AdjustClass(); if(Class == GADGETUP) { /* Stop formatting? */ if(GadgetID == 8) { Error = -42; goto WriteError; } } } if((Count++) == 6) break; Delay(TICKS_PER_SECOND >> 1); } SetAPen(Window -> RPort,0); RectFill(Window -> RPort,4,23 + TopEdge,323,34 + TopEdge); SetAPen(Window -> RPort,1); } } CopyMemQuick(CheckTrack,DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR); } /* Are we to format the whole disk? */ if(!Fast) { DiskRequest -> iotd_Req . io_Command = ETD_FORMAT; DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack; DiskRequest -> iotd_Req . io_Length = NUMSECS * NUMHEADS * TD_SECTOR; for(i = 0 ; i < NUMCYLS ; i++) if(Error = DiskFormat(i)) break; if(Verify && !Error) { DiskRequest -> iotd_Req . io_Command = ETD_READ; for(i = NUMCYLS - 1 ; i >= 0 && Verify ; i--) if(Error = DiskRead(i)) break; } } if(!Error) { if(Install || Fast) { ClearBlock(DiskTrack); if(FFS) DiskTrack[0] = ID_FFS_DISK; else DiskTrack[0] = ID_DOS_DISK; /* Take the standard boot block? */ if(Install) { CopyMemQuick(Standard,DiskTrack,sizeof(Standard)); if(FFS) DiskTrack[0] = ID_FFS_DISK; else DiskTrack[0] = ID_DOS_DISK; DiskTrack[1] = FixBootSum(DiskTrack); } DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack; if(Error = DiskWrite(0,0)) { i = 0; goto WriteError; } if(Fast) { DiskRequest -> iotd_Req . io_Data = (APTR)RootTrack; if(Error = DiskWrite((NUMTRACKS / 2) * NUMSECS * TD_SECTOR,40)) { i = 40; goto WriteError; } } } } else { WriteError: if(Error > -42) SPrintf((char *)InfoText . IText,"Write error Nº%ld, track %ld!",Error,i); else { if(Error == -42) Strcpy((char *)InfoText . IText,"*** Format aborted ***"); else SPrintf((char *)InfoText . IText,"Verification error on track %ld!",i); } GeneralError = TRUE; } DiskRequest -> iotd_Req . io_Command = ETD_UPDATE; DoIO(DiskRequest); DiskRequest -> iotd_Req . io_Command = TD_MOTOR; DiskRequest -> iotd_Req . io_Length = 0; DoIO(DiskRequest); } else { Strcpy(InfoText . IText,"Disk ist write protected!"); GeneralError = TRUE; } } else { Strcpy(InfoText . IText,"No disk in drive!"); GeneralError = TRUE; } FreeMem(SectorLabel,NUMSECS * NUMHEADS * TD_LABELSIZE); } FreeMem(RootTrack,NUMSECS * NUMHEADS * TD_SECTOR); } FreeMem(DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR); } else { Strcpy(InfoText . IText,"Out of memory!"); GeneralError = TRUE; } FreeMem(CheckTrack,NUMSECS * NUMHEADS * TD_SECTOR); } else { Strcpy(InfoText . IText,"Out of memory!"); GeneralError = TRUE; } ClearPort(); return(GeneralError); } /* CentreWindow(): * * Centre a new window under the mouse pointer. I didn't * want to use the req.library function for this purpose * and wrote my own special creation. */ VOID CentreWindow(struct NewWindow *New,USHORT OffsetX,USHORT OffsetY) { struct Screen PublicScreen; /* Get the screen data. */ if(GetScreenData(&PublicScreen,sizeof(struct Screen),New -> Type,New -> Screen)) { /* Put it under the mouse pointer. */ New -> LeftEdge = PublicScreen . MouseX - OffsetX; New -> TopEdge = PublicScreen . MouseY - OffsetY; /* Adjust the x position. */ while(New -> LeftEdge + New -> Width > PublicScreen . Width) New -> LeftEdge--; while(New -> LeftEdge < 0) New -> LeftEdge++; /* Adjust the y position. */ while(New -> TopEdge + New -> Height > PublicScreen . Height) New -> TopEdge--; while(New -> TopEdge < 0) New -> TopEdge++; } } /* DecrementUsage(): * * Decrement the number of currently running Formatters * and remove the the MsgPort if the current Formatter is * the last one to terminate. */ VOID DecrementUsage() { Forbid(); if(!(--GlobalPort -> NumPrgs)) { RemPort(&GlobalPort -> Port); FreeMem(GlobalPort,sizeof(struct FormatterPort)); } Permit(); } /* CloseAll(): * * Closes devices and locks the shop. */ VOID CloseAll(BYTE ReturnCode) { if(TimeRequest) { if(TimeRequest -> tr_node . io_Device) CloseDevice(TimeRequest); DeleteExtIO(TimeRequest); } if(TimePort) DeletePort(TimePort); if(DiskRequest) { struct TDU_PublicUnit *PublicUnit; SHORT i; if(DiskRequest -> iotd_Req . io_Device) CloseDevice(DiskRequest); for(i = 0 ; i < 4 ; i++) { if(OldSteps[i]) { if(!OpenDevice(TD_NAME,i,DiskRequest,0)) { PublicUnit = (struct TDU_PublicUnit *)DiskRequest -> iotd_Req . io_Unit; PublicUnit -> tdu_StepDelay = OldSteps[i]; CloseDevice(DiskRequest); } } } DeleteExtIO(DiskRequest); } if(DiskPort) DeletePort(DiskPort); if(Window) { ClearMenuStrip(Window); CloseWindow(Window); } exit(ReturnCode); } /* OpenAll(): * * Opens the devices we need and also the window. */ VOID OpenAll() { struct TDU_PublicUnit *PublicUnit; SHORT i; if(!(TimePort = CreatePort(NULL,0))) CloseAll(RETURN_FAIL + 0); if(!(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest)))) CloseAll(RETURN_FAIL + 1); if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0)) CloseAll(RETURN_FAIL + 2); if(!(DiskPort = CreatePort(NULL,0))) CloseAll(RETURN_FAIL + 3); if(!(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD)))) CloseAll(RETURN_FAIL + 4); Forbid(); for(i = 0 ; i < 4 ; i++) { if(!OpenDevice(TD_NAME,i,DiskRequest,0)) { PublicUnit = (struct TDU_PublicUnit *)DiskRequest -> iotd_Req . io_Unit; OldSteps[i] = PublicUnit -> tdu_StepDelay; CloseDevice(DiskRequest); } else { OldSteps[i] = 0; DelayGadgets[i] . Flags |= GADGDISABLED; } } Permit(); SetStepDelays(OldSteps); if(OpenDevice(TD_NAME,DriveUnit,DiskRequest,0)) CloseAll(RETURN_FAIL + 5); TopEdge = GfxBase -> DefaultFont -> tf_YSize - 8; for(i = 0 ; i < 10 ; i++) FormatGadget[i] . TopEdge += TopEdge; NewWindow . Height += TopEdge; CentreWindow(&NewWindow,FormatGadget[8] . LeftEdge + (FormatGadget[8] . Width >> 1),FormatGadget[8] . TopEdge + (FormatGadget[8] . Height >> 1)); if(!(Window = OpenWindow(&NewWindow))) CloseAll(RETURN_FAIL + 6); } /* main(): * * That's where all the trouble starts. */ VOID main(int argc,char **argv) { static char *Drive = "DFx:"; BYTE Error,OldUnit,DiskInDrive; ULONG Time1,Time2,Dummy; SHORT i; /* Try to find the global MsgPort. */ Forbid(); if(!(GlobalPort = (struct FormatterPort *)FindPort(PORTNAME))) { /* Didn't find it, create it now. */ if(GlobalPort = (struct FormatterPort *)AllocMem(sizeof(struct FormatterPort),MEMF_PUBLIC | MEMF_CLEAR)) { GlobalPort -> Port . mp_Node . ln_Name = PORTNAME; GlobalPort -> Port . mp_Node . ln_Type = NT_MSGPORT; GlobalPort -> Port . mp_Node . ln_Pri = 1; GlobalPort -> Port . mp_Flags = PA_IGNORE; AddPort(&GlobalPort -> Port); } } /* Increment the user count. */ if(GlobalPort) GlobalPort -> NumPrgs++; Permit(); /* Didn't create the port. */ if(!GlobalPort) { if(argc) Printf("Formatter: Unable to create global MsgPort.\a\n"); exit(RETURN_FAIL); } /* Do we expect CLI arguments? */ if(argc > 1) { char TestString[5]; /* Enable debug? */ if(argv[ARG_DEBUG]) DebugFlag = TRUE; /* Which disk drive? */ if(argv[ARG_DRIVE]) { /* Does it match 'DFx:'? */ if(Strlen(argv[ARG_DRIVE]) != 4) { DecrementUsage(); Puts(CLI_Help); exit(RETURN_WARN); } Strcpy(TestString,argv[ARG_DRIVE]); TestString[2] = 'x'; if(Strcmp(Drive,TestString)) { DecrementUsage(); Puts(CLI_Help); exit(RETURN_WARN); } /* Can we find the device? */ if(!FindDevice(argv[ARG_DRIVE])) { DecrementUsage(); Printf("Formatter: Unable to find device '%s'.\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } DriveUnit = argv[ARG_DRIVE][2] - '0'; } /* Enable Auto-start? */ if(argv[ARG_AUTOSTART]) { FormatGadget[4] . Flags |= SELECTED; FormatMenuItem[2] . Flags |= CHECKED; } /* Enable verification? */ if(argv[ARG_VERIFY]) { FormatGadget[5] . Flags |= SELECTED; FormatMenuItem[4] . Flags |= CHECKED; } /* Enable fast format? */ if(argv[ARG_FAST]) { FormatGadget[6] . Flags |= SELECTED; FormatMenuItem[3] . Flags |= CHECKED; } /* Enable disk installation? */ if(argv[ARG_INSTALL]) { FormatGadget[7] . Flags |= SELECTED; FormatMenuItem[5] . Flags |= CHECKED; } if(argv[ARG_FFS]) FormatMenuItem[6] . Flags |= CHECKED; } Forbid(); /* Is the desired drive already occupied? */ if(argc && argv[ARG_DRIVE]) { if(GlobalPort -> DriveInUse[DriveUnit]) { DecrementUsage(); Permit(); Printf("Formatter: A different Formatter task is currently using device '%s'.\a\n",argv[ARG_DRIVE]); exit(RETURN_FAIL); } else GlobalPort -> DriveInUse[DriveUnit] = TRUE; } else { /* Try to find the first disk drive * currently not in use. */ DriveUnit = -1; for(i = 0 ; i < 4 ; i++) { if(!GlobalPort -> DriveInUse[i]) { DriveUnit = i; break; } } /* Didn't find an unused drive. */ if(DriveUnit == -1) { DecrementUsage(); Permit(); DisplayBeep(NULL); exit(RETURN_FAIL); } else GlobalPort -> DriveInUse[DriveUnit] = TRUE; } Permit(); /* Take which disk name? */ if(argc) Strcpy(FormatText,(argv[ARG_NAME] ? argv[ARG_NAME] : "Blank")); else Strcpy(FormatText,"Blank"); /* Set the start gadget text. */ FormatIntTxt[8] . IText = (UBYTE *)"Start"; FormatMenuIntTxt[14] . IText = FormatInfoText[0]; /* Open the resources. */ OpenAll(); /* The timer request gets initialized. */ TimeRequest -> tr_node . io_Command = TR_ADDREQUEST; TimeRequest -> tr_time . tv_micro = MILLION / 2; /* Draw the track indicator. */ DrawImage(Window -> RPort,&PanelImage,4,11 + TopEdge); /* Mark the device gadgets. */ for(i = 0 ; i < 4 ; i++) { Drive[2] = '0' + i; if(!FindDevice(Drive)) { FormatGadget[i] . Flags |= GADGDISABLED; FormatMenuItem[8 + i] . Flags &= ~ITEMENABLED; } else FormatGadget[i] . Flags &= ~GADGDISABLED; if(i != DriveUnit) RefreshGadget(Window,&FormatGadget[i],0); else { RefreshGadget(Window,&FormatGadget[i],3); FormatMenuItem[8 + i] . Flags |= CHECKED; } } /* Build the track offset table. */ for(i = 0 ; i < NUMCYLS ; i++) OffsetTable[i] = i * (NUMSECS * NUMHEADS * TD_SECTOR); /* Inhibit DFx:. */ Drive[2] = '0' + DriveUnit; Inhibit(Drive,TRUE); /* Is there a disk in the drive? */ DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE; DoIO(DiskRequest); DiskInDrive = DiskRequest -> iotd_Req . io_Actual; /* Enable the menu. */ SetMenuStrip(Window,&FormatMenu); Window -> Flags &= ~RMBTRAP; /* Go into loop. */ FOREVER { /* Wait half a second. */ DoIO(TimeRequest); /* Auto-start enabled? */ if(AutoStart) { /* Has a disk been inserted? */ DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE; DoIO(DiskRequest); if(!DiskRequest -> iotd_Req . io_Actual && (DiskRequest -> iotd_Req . io_Actual != DiskInDrive)) { DiskInDrive = DiskRequest -> iotd_Req . io_Actual; GadgetID = 8; Class = GADGETUP; goto CheckClass; } DiskInDrive = DiskRequest -> iotd_Req . io_Actual; } /* News in the mail? */ if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { Class = Massage -> Class; Code = Massage -> Code; GadgetID = ((struct Gadget *)Massage -> IAddress) -> GadgetID; ReplyMsg(Massage); /* Picked a menu item? */ if(Class == MENUPICK) AdjustClass(); /* Close the window. */ if(Class == CLOSEWINDOW) { Drive[2] = '0' + DriveUnit; Inhibit(Drive,FALSE); GlobalPort -> DriveInUse[DriveUnit] = FALSE; DecrementUsage(); CloseAll(RETURN_OK); } Error = 0; /* Check the gadgets. */ CheckClass: if(Class == GADGETUP) { switch(GadgetID) { case 0: case 1: case 2: case 3: OldUnit = DriveUnit; Drive[2] = '0' + GadgetID; if(!FindDevice(Drive)) break; if(GadgetID != DriveUnit) { Forbid(); if(GlobalPort -> DriveInUse[GadgetID]) { Permit(); DisplayBeep(Window -> WScreen); break; } GlobalPort -> DriveInUse[GadgetID] = TRUE; GlobalPort -> DriveInUse[OldUnit] = FALSE; Permit(); Drive[2] = '0' + DriveUnit; Inhibit(Drive,FALSE); if(!Error) CloseDevice(DiskRequest); DriveUnit = GadgetID; for(i = 0 ; i < 4 ; i++) { if(i != DriveUnit) RefreshGadget(Window,&FormatGadget[i],0); else RefreshGadget(Window,&FormatGadget[i],3); if((FormatMenuItem[8 + i] . Flags & ITEMENABLED) && i == DriveUnit) FormatMenuItem[8 + i] . Flags |= CHECKED; else FormatMenuItem[8 + i] . Flags &= ~CHECKED; } Drive[2] = '0' + DriveUnit; Inhibit(Drive,TRUE); if(Error = OpenDevice(TD_NAME,DriveUnit,DiskRequest,0)) { GadgetID = OldUnit; goto CheckClass; } } break; case 4: FormatMenuItem[2] . Flags ^= CHECKED; break; case 5: FormatMenuItem[4] . Flags ^= CHECKED; break; case 6: FormatMenuItem[3] . Flags ^= CHECKED; break; case 7: FormatMenuItem[5] . Flags ^= CHECKED; break; case 8: DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE; DoIO(DiskRequest); DiskInDrive = DiskRequest -> iotd_Req . io_Actual; FormatIntTxt[8] . IText = (UBYTE *)"Stop!"; RefreshGadget(Window,&FormatGadget[8],3); for(i = 0 ; i < 4 ; i++) FormatGadget[i] . Flags |= GADGDISABLED; SetAPen(Window -> RPort,0); RectFill(Window -> RPort,4,23 + TopEdge,323,34 + TopEdge); SetAPen(Window -> RPort,1); FormatGadget[4] . Flags |= GADGDISABLED; RefreshGadget(Window,&FormatGadget[4],0); FormatGadget[6] . Flags |= GADGDISABLED; RefreshGadget(Window,&FormatGadget[6],0); FormatGadget[9] . Flags |= GADGDISABLED; RefreshGadget(Window,&FormatGadget[9],0); FormatMenuItem[ 0] . Flags &= ~ITEMENABLED; FormatMenuItem[ 2] . Flags &= ~ITEMENABLED; FormatMenuItem[ 3] . Flags &= ~ITEMENABLED; FormatMenuItem[ 6] . Flags &= ~ITEMENABLED; FormatMenuItem[16] . Flags &= ~ITEMENABLED; FormatMenuItem[13] . Flags &= ~ITEMENABLED; FormatMenuIntTxt[14] . IText = FormatInfoText[1]; for(i = 0 ; i < 4 ; i++) FormatMenuItem[8 + i] . Flags &= ~ITEMENABLED; CurrentTime(&Time1,&Dummy); Error = Formatter((char *)FormatText); CurrentTime(&Time2,&Dummy); if(!Error) { Drive[2] = '0' + DriveUnit; Inhibit(Drive,FALSE); Delay(3 * TICKS_PER_SECOND); Inhibit(Drive,TRUE); } FormatGadget[4] . Flags &= ~GADGDISABLED; RefreshGadget(Window,&FormatGadget[4],0); FormatGadget[6] . Flags &= ~GADGDISABLED; RefreshGadget(Window,&FormatGadget[6],0); FormatGadget[9] . Flags &= ~GADGDISABLED; RefreshGadget(Window,&FormatGadget[9],0); for(i = 0 ; i < 4 ; i++) { Drive[2] = '0' + i; if(FindDevice(Drive)) FormatMenuItem[8 + i] . Flags |= ITEMENABLED; } FormatMenuItem[ 0] . Flags |= ITEMENABLED; FormatMenuItem[ 2] . Flags |= ITEMENABLED; FormatMenuItem[ 3] . Flags |= ITEMENABLED; FormatMenuItem[ 6] . Flags |= ITEMENABLED; FormatMenuItem[16] . Flags |= ITEMENABLED; FormatMenuItem[13] . Flags |= ITEMENABLED; FormatMenuIntTxt[14] . IText = FormatInfoText[0]; SetAPen(Window -> RPort,0); RectFill(Window -> RPort,4,23 + TopEdge,323,34 + TopEdge); SetAPen(Window -> RPort,1); if(Error) { InfoText . LeftEdge = 4 + (320 - 8 * Strlen(InfoText . IText)) / 2; PrintIText(Window -> RPort,&InfoText,0,TopEdge); DisplayBeep(Window -> WScreen); } else { SPrintf((char *)InfoText . IText,"Formatting time %ld:%02ld",abs(Time2 - Time1) / 60,abs(Time2 - Time1) % 60); InfoText . LeftEdge = 4 + (320 - 8 * Strlen(InfoText . IText)) / 2; PrintIText(Window -> RPort,&InfoText,0,TopEdge); } for(i = 0 ; i < 4 ; i++) { Drive[2] = '0' + i; if(!FindDevice(Drive)) FormatGadget[i] . Flags |= GADGDISABLED; else FormatGadget[i] . Flags &= ~GADGDISABLED; if(i != DriveUnit) RefreshGadget(Window,&FormatGadget[i],0); else RefreshGadget(Window,&FormatGadget[i],3); } FormatIntTxt[8] . IText = (UBYTE *)"Start"; RefreshGadget(Window,&FormatGadget[8],0); break; default:break; } } } } }