home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
440.lha
/
Formatter_v2.7
/
Formatter.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-13
|
61KB
|
2,525 lines
/* $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;
}
}
}
}
}