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 >
C/C++ Source or Header  |  1990-11-13  |  61KB  |  2,525 lines

  1. /* $Revision Header * Header built automatically - do not edit! *************
  2.  *
  3.  *    (C) Copyright 1990 by MXM
  4.  *
  5.  *    Name .....: Formatter.c
  6.  *    Created ..: Thursday 31-May-90 19:49
  7.  *    Revision .: 7
  8.  *
  9.  *    Date            Author          Comment
  10.  *    =========       ========        ====================
  11.  *    20-Sep-90       Olsen           If autostart enabled, displays the
  12.  *                                    name of the disk inserted.
  13.  *    29-Aug-90       Olsen           Write verification uses blitter
  14.  *    04-Aug-90       Olsen           Sector labels are cleared
  15.  *    02-Aug-90       Olsen           Gadget/menu coordination fixed
  16.  *    24-Jul-90       Olsen           Removed bug in formatting routine,
  17.  *                                    added disk validation break,
  18.  *                                    fixed the bootblock checksum
  19.  *    08-Jul-90       Olsen           Sped up the formatting process
  20.  *    08-Jun-90       Olsen           Added the menu
  21.  *    08-Jun-90       Olsen           Fixed some bugs
  22.  *    31-May-90       Olsen           Created this file!
  23.  *
  24.  ****************************************************************************
  25.  *
  26.  *    This file contains the main routines used by Formatter.c
  27.  *
  28.  * $Revision Header ********************************************************/
  29.  
  30.     /* Prototypes for this module. */
  31.  
  32. BYTE            FindDevice(char *DevName);
  33. VOID            RefreshGadget(struct Window *Window,struct Gadget *Gadget,BYTE Colour);
  34. VOID            ClearPort(VOID);
  35. VOID            AdjustClass(VOID);
  36. VOID            ConvertString(char *ToString,char *FromString);
  37. ULONG            FixBlockSum(ULONG *Array);
  38. ULONG            FixBootSum(ULONG *Array);
  39. VOID            SetBitmapBlock(ULONG *BitmapData,SHORT Block,BYTE SetFlag);
  40. VOID            ClearBlock(ULONG *Block);
  41. VOID            Inhibit(char *Drive,BYTE Bool);
  42. BYTE            CompareTracks(ULONG *Track1,ULONG *Track2);
  43. BYTE            DiskRead(BYTE Track);
  44. BYTE            DiskWrite(ULONG Offset,BYTE Track);
  45. BYTE            DiskFormat(BYTE Track);
  46. BYTE            Formatter(char *DiskName);
  47. VOID            CentreWindow(struct NewWindow *New,USHORT OffsetX,USHORT OffsetY);
  48. VOID            DecrementUsage(VOID);
  49. VOID            CloseAll(BYTE ReturnCode);
  50. VOID            OpenAll(VOID);
  51. LONG            Strlen(VOID *String);
  52. VOID            Strcpy(VOID *Dest,VOID *Source);
  53. VOID            main(int argc,char **argv);
  54.  
  55.     /* Assembly language string routines. */
  56.  
  57. #pragma regcall(Strlen(a0))
  58. #pragma regcall(Strcpy(a0,a1))
  59.  
  60.     /* Window interaction. */
  61.  
  62. struct Window        *Window;
  63. struct IntuiMessage    *Massage;
  64. ULONG             Class,Code;
  65. BYTE             GadgetID;
  66.  
  67.     /* Global information port. */
  68.  
  69. struct FormatterPort    *GlobalPort;
  70.  
  71. #define PORTNAME     "Formatter"
  72.  
  73.     /* Disk interaction. */
  74.  
  75. struct MsgPort        *DiskPort;
  76. struct IOExtTD        *DiskRequest;
  77. struct MsgPort        *TimePort;
  78. struct timerequest    *TimeRequest;
  79. ULONG            *DiskTrack,*CheckTrack,*RootTrack,*SectorLabel;
  80. BYTE             DriveUnit = 0;
  81. ULONG             OffsetTable[NUMCYLS];
  82.  
  83.     /* Debug flag. */
  84.  
  85. BYTE             DebugFlag = FALSE;
  86.  
  87.     /* Boolean flags. */
  88.  
  89. #define AutoStart    (FormatGadget[4] . Flags & SELECTED)
  90. #define Verify        (FormatGadget[5] . Flags & SELECTED)
  91. #define Fast        (FormatGadget[6] . Flags & SELECTED)
  92. #define Install        (FormatGadget[7] . Flags & SELECTED)
  93. #define FFS        (FormatMenuItem[6].Flags & CHECKED)
  94.  
  95.     /* Arp CLI info. */
  96.  
  97. char *CLI_Template    = "Drive,NAME/K,F=FAST/S,I=INSTALL/S,V=VERIFY/S,A=AUTOSTART/S,FFS/S,DEBUG/S";
  98. char *CLI_Help        = "\nUsage: Formatter [DF0: | DF1: | DF2: | DF3:] [Name]\n                 [FAST] [INSTALL] [VERIFY] [AUTOSTART] [FFS]\n";
  99.  
  100.     /* Argument vector offsets. */
  101.  
  102. #define ARG_DRIVE    1
  103. #define ARG_NAME    2
  104. #define ARG_FAST    3
  105. #define ARG_INSTALL    4
  106. #define ARG_VERIFY    5
  107. #define ARG_AUTOSTART    6
  108. #define ARG_FFS        7
  109. #define ARG_DEBUG    8
  110.  
  111.     /* Drive step delay modification. */
  112.  
  113. struct FileRequester    *DelayFileReq;
  114. ULONG             OldSteps[4];
  115.  
  116.     /* Offset from window top edge. */
  117.  
  118. LONG TopEdge;
  119.  
  120.     /* Default font for text rendering. */
  121.  
  122. struct TextAttr DefaultFont =
  123. {
  124.     (STRPTR)"topaz.font",
  125.     8,
  126.     FS_NORMAL,
  127.     FPF_ROMFONT
  128. };
  129.  
  130. struct TextAttr BoldFont =
  131. {
  132.     (STRPTR)"topaz.font",
  133.     8,
  134.     FSF_BOLD,
  135.     FPF_ROMFONT
  136. };
  137.  
  138.     /* A whole lot of intuition & graphics data. */
  139.  
  140. struct IntuiText InfoText = { 1,0,JAM1,0,25,&DefaultFont,(UBYTE *)"                                        ",NULL };
  141.  
  142. struct IntuiText FormatIntTxt[10] =
  143. {
  144.     {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF0:",        NULL},
  145.     {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF1:",        NULL},
  146.     {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF2:",        NULL},
  147.     {1,0,0, 21,2,&DefaultFont,(UBYTE *)"DF3:",        NULL},
  148.     {1,0,0, 20,2,&DefaultFont,(UBYTE *)"Auto start",    NULL},
  149.     {1,0,0, 12,2,&DefaultFont,(UBYTE *)"Verify Write",    NULL},
  150.     {1,0,0, 16,2,&DefaultFont,(UBYTE *)"Fast format",    NULL},
  151.     {1,0,0, 12,2,&DefaultFont,(UBYTE *)"Install Disk",    NULL},
  152.     {1,0,0, 12,9,&DefaultFont,(UBYTE *)NULL,        NULL},
  153.     {1,0,0,-48,0,&DefaultFont,(UBYTE *)"Name:",        NULL}
  154. };
  155.  
  156. UBYTE FormatText[32],UndoFormatText[32];
  157.  
  158. struct StringInfo FormatStringInfo = { FormatText,UndoFormatText,0,32,32,0,0,0,0,NULL,NULL,NULL };
  159.  
  160. SHORT FormatBorderData[] =
  161. {
  162.     -1,-1, 74,-1, 74,12,-1,12,-1,-1,
  163.     -2,-1, 75,-1, 75,12,-2,12,-2,-1,
  164.     -1,-1, 74,-1, 74,12,-1,12,-1,-1,
  165.     -2,-1, 75,-1, 75,12,-2,12,-2,-1,
  166.     -1,-1, 74,-1, 74,12,-1,12,-1,-1,
  167.     -2,-1, 75,-1, 75,12,-2,12,-2,-1,
  168.     -1,-1, 74,-1, 74,12,-1,12,-1,-1,
  169.     -2,-1, 75,-1, 75,12,-2,12,-2,-1,
  170.     -1,-1,120,-1,120,12,-1,12,-1,-1,
  171.     -2,-1,121,-1,121,12,-2,12,-2,-1,
  172.     -1,-1,120,-1,120,12,-1,12,-1,-1,
  173.     -2,-1,121,-1,121,12,-2,12,-2,-1,
  174.     -1,-1,120,-1,120,12,-1,12,-1,-1,
  175.     -2,-1,121,-1,121,12,-2,12,-2,-1,
  176.     -1,-1,120,-1,120,12,-1,12,-1,-1,
  177.     -2,-1,121,-1,121,12,-2,12,-2,-1,
  178.     -2,-1, 66,-1, 66,27,-2,27,-2,-1,
  179.     -1,-1, 65,-1, 65,27,-1,27,-1,-1,
  180.     -1,-1,256,-1,256, 8,-1, 8,-1,-1,
  181.     -2,-1,257,-1,257, 8,-2, 8,-2,-1
  182. };
  183.  
  184. struct Border FormatBorder[] =
  185. {
  186.     {0,0,1,0,0,5,&FormatBorderData[  0],&FormatBorder[ 1]},
  187.     {0,0,1,0,0,5,&FormatBorderData[ 10],NULL},
  188.     {0,0,1,0,0,5,&FormatBorderData[ 20],&FormatBorder[ 3]},
  189.     {0,0,1,0,0,5,&FormatBorderData[ 30],NULL},
  190.     {0,0,1,0,0,5,&FormatBorderData[ 40],&FormatBorder[ 5]},
  191.     {0,0,1,0,0,5,&FormatBorderData[ 50],NULL},
  192.     {0,0,1,0,0,5,&FormatBorderData[ 60],&FormatBorder[ 7]},
  193.     {0,0,1,0,0,5,&FormatBorderData[ 70],NULL},
  194.     {0,0,1,0,0,5,&FormatBorderData[ 80],&FormatBorder[ 9]},
  195.     {0,0,1,0,0,5,&FormatBorderData[ 90],NULL},
  196.     {0,0,1,0,0,5,&FormatBorderData[100],&FormatBorder[11]},
  197.     {0,0,1,0,0,5,&FormatBorderData[110],NULL},
  198.     {0,0,1,0,0,5,&FormatBorderData[120],&FormatBorder[13]},
  199.     {0,0,1,0,0,5,&FormatBorderData[130],NULL},
  200.     {0,0,1,0,0,5,&FormatBorderData[140],&FormatBorder[15]},
  201.     {0,0,1,0,0,5,&FormatBorderData[150],NULL},
  202.     {0,0,1,0,0,5,&FormatBorderData[160],&FormatBorder[17]},
  203.     {0,0,1,0,0,5,&FormatBorderData[170],NULL},
  204.     {0,0,1,0,0,5,&FormatBorderData[180],&FormatBorder[19]},
  205.     {0,0,1,0,0,5,&FormatBorderData[190],NULL}
  206. };
  207.  
  208. #define IMMEDIATE    (RELVERIFY | GADGIMMEDIATE)
  209. #define TOGGLE        (RELVERIFY | GADGIMMEDIATE | TOGGLESELECT)
  210.  
  211. struct Gadget FormatGadget[10] =
  212. {
  213.     {&FormatGadget[1],  6,67, 74,12,0,IMMEDIATE,    BOOLGADGET,    (APTR)&FormatBorder[ 0],NULL,&FormatIntTxt[0],NULL,NULL,            0,NULL},
  214.     {&FormatGadget[2], 87,67, 74,12,0,IMMEDIATE,    BOOLGADGET,    (APTR)&FormatBorder[ 2],NULL,&FormatIntTxt[1],NULL,NULL,            1,NULL},
  215.     {&FormatGadget[3],168,67, 74,12,0,IMMEDIATE,    BOOLGADGET,    (APTR)&FormatBorder[ 4],NULL,&FormatIntTxt[2],NULL,NULL,            2,NULL},
  216.     {&FormatGadget[4],249,67, 74,12,0,IMMEDIATE,    BOOLGADGET,    (APTR)&FormatBorder[ 6],NULL,&FormatIntTxt[3],NULL,NULL,            3,NULL},
  217.     {&FormatGadget[5],  6,37,120,12,0,TOGGLE,    BOOLGADGET,    (APTR)&FormatBorder[ 8],NULL,&FormatIntTxt[4],NULL,NULL,            4,NULL},
  218.     {&FormatGadget[6],  6,52,120,12,0,TOGGLE,    BOOLGADGET,    (APTR)&FormatBorder[10],NULL,&FormatIntTxt[5],NULL,NULL,            5,NULL},
  219.     {&FormatGadget[7],132,37,120,12,0,TOGGLE,    BOOLGADGET,    (APTR)&FormatBorder[12],NULL,&FormatIntTxt[6],NULL,NULL,            6,NULL},
  220.     {&FormatGadget[8],132,52,120,12,0,TOGGLE,    BOOLGADGET,    (APTR)&FormatBorder[14],NULL,&FormatIntTxt[7],NULL,NULL,            7,NULL},
  221.     {&FormatGadget[9],258,37, 65,27,0,IMMEDIATE,    BOOLGADGET,    (APTR)&FormatBorder[16],NULL,&FormatIntTxt[8],NULL,NULL,            8,NULL},
  222.     {NULL,             67,82,256, 8,0,IMMEDIATE,    STRGADGET,    (APTR)&FormatBorder[18],NULL,&FormatIntTxt[9],NULL,(APTR)&FormatStringInfo,    9,NULL}
  223. };
  224.  
  225. UBYTE *FormatInfoText[2] =
  226. {
  227.     (UBYTE *)"   Start formatting",
  228.     (UBYTE *)"   Stop formatting"
  229. };
  230.  
  231. struct IntuiText FormatMenuIntTxt[17] =
  232. {
  233.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   About...",            NULL},
  234.     {0,0,0,0,1,&BoldFont,    (UBYTE *)"________________________",    NULL},
  235.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Auto start",        NULL},
  236.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Fast format",        NULL},
  237.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Verify write",        NULL},
  238.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Install disk",        NULL},
  239.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Use FFS",            NULL},
  240.     {0,0,0,0,1,&BoldFont,    (UBYTE *)"________________________",    NULL},
  241.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Drive DF0:",        NULL},
  242.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Drive DF1:",        NULL},
  243.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Drive DF2:",        NULL},
  244.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Drive DF3:",        NULL},
  245.     {0,0,0,0,1,&BoldFont,    (UBYTE *)"________________________",    NULL},
  246.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Modify stepdelay",        NULL},
  247.     {0,0,0,0,1,&DefaultFont,NULL,                    NULL},
  248.     {0,0,0,0,1,&BoldFont,    (UBYTE *)"________________________",    NULL},
  249.     {0,0,0,0,1,&DefaultFont,(UBYTE *)"   Quit",            NULL}
  250. };
  251.  
  252. struct MenuItem FormatMenuItem[17] =
  253. {
  254.     {&FormatMenuItem[ 1],    0,  0,192,10, 86,0,(APTR)&FormatMenuIntTxt[ 0],NULL,63,NULL,NULL},
  255.     {&FormatMenuItem[ 2],    0,  3,192,10,210,0,(APTR)&FormatMenuIntTxt[ 1],NULL, 0,NULL,NULL},
  256.     {&FormatMenuItem[ 3],    0, 13,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 2],NULL,65,NULL,NULL},
  257.     {&FormatMenuItem[ 4],    0, 23,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 3],NULL,70,NULL,NULL},
  258.     {&FormatMenuItem[ 5],    0, 33,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 4],NULL,86,NULL,NULL},
  259.     {&FormatMenuItem[ 6],    0, 43,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 5],NULL,73,NULL,NULL},
  260.     {&FormatMenuItem[ 7],    0, 53,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 6],NULL,70,NULL,NULL},
  261.     {&FormatMenuItem[ 8],    0, 56,192,10,210,0,(APTR)&FormatMenuIntTxt[ 7],NULL, 0,NULL,NULL},
  262.     {&FormatMenuItem[ 9],    0, 66,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 8],NULL,49,NULL,NULL},
  263.     {&FormatMenuItem[10],    0, 76,192,10, 95,0,(APTR)&FormatMenuIntTxt[ 9],NULL,50,NULL,NULL},
  264.     {&FormatMenuItem[11],    0, 86,192,10, 95,0,(APTR)&FormatMenuIntTxt[10],NULL,51,NULL,NULL},
  265.     {&FormatMenuItem[12],    0, 96,192,10, 95,0,(APTR)&FormatMenuIntTxt[11],NULL,52,NULL,NULL},
  266.     {&FormatMenuItem[13],    0, 99,192,10,210,0,(APTR)&FormatMenuIntTxt[12],NULL, 0,NULL,NULL},
  267.     {&FormatMenuItem[14],    0,109,192,10, 86,0,(APTR)&FormatMenuIntTxt[13],NULL,77,NULL,NULL},
  268.     {&FormatMenuItem[15],    0,119,192,10, 86,0,(APTR)&FormatMenuIntTxt[14],NULL,83,NULL,NULL},
  269.     {&FormatMenuItem[16],    0,122,192,10,210,0,(APTR)&FormatMenuIntTxt[15],NULL, 0,NULL,NULL},
  270.     {NULL,            0,132,192,10, 86,0,(APTR)&FormatMenuIntTxt[16],NULL,81,NULL,NULL}
  271. };
  272.  
  273. struct Menu FormatMenu = {NULL,0,0,112,0,257,"Formatter 2.7",&FormatMenuItem[0]};
  274.  
  275. struct IntuiText ReqIntTxt[9] =
  276. {
  277.     {2,0,0,  3, 3,&DefaultFont,(UBYTE *)"Copy me, I wish to travel!",    NULL},
  278.     {2,0,0, 10, 5,&BoldFont,   (UBYTE *)"Formatter 2.7",            &ReqIntTxt[2]},
  279.     {3,0,0,127, 5,&DefaultFont,(UBYTE *)"© Copyright 1990 by MXM",        &ReqIntTxt[3]},
  280.     {0,0,0,127,17,&DefaultFont,(UBYTE *)"Olaf Barthel",            &ReqIntTxt[4]},
  281.     {0,0,0,127,25,&DefaultFont,(UBYTE *)"Brabeckstrasse 35",        &ReqIntTxt[5]},
  282.     {0,0,0,127,33,&DefaultFont,(UBYTE *)"D-3000 Hannover 71",        &ReqIntTxt[6]},
  283.     {2,0,0, 67,17,&DefaultFont,(UBYTE *)"Author",                &ReqIntTxt[7]},
  284.     {2,0,0, 11,45,&DefaultFont,(UBYTE *)"Shareware fee",            &ReqIntTxt[8]},
  285.     {0,0,0,127,45,&DefaultFont,(UBYTE *)"10$ US or DM 15,-",            NULL}
  286. };
  287.  
  288. SHORT ReqBorderData[] =
  289. {
  290.     -1,-1,214,-1,214,14,-1,14,-1,-1,
  291.     -2,-1,215,-1,215,14,-2,14,-2,-1,
  292.      0, 0,311, 0,311,75, 0,75, 0, 0,
  293.      0, 0,311, 0,311,75, 0,75, 0, 0
  294. };
  295.  
  296. struct Border ReqBorder[] =
  297. {
  298.     {0,0,2,0,0,5,&ReqBorderData[ 0],&ReqBorder[1]},
  299.     {0,0,2,0,0,5,&ReqBorderData[10],NULL},
  300.     {4,2,0,0,0,5,&ReqBorderData[20],&ReqBorder[3]},
  301.     {5,2,0,0,0,5,&ReqBorderData[30],NULL}
  302. };
  303.  
  304. struct Gadget ReqGadget = {NULL,53,58,214,14,0,3,4097,(APTR)&ReqBorder[0],NULL,&ReqIntTxt[0],NULL,NULL,0,NULL};
  305.  
  306. struct Requester Req;
  307.  
  308. struct IntuiText DelayIntTxt[9] =
  309. {
  310.     {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF0:",                NULL},
  311.     {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF1:",                NULL},
  312.     {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF2:",                NULL},
  313.     {2,1,0,-91, 0,&DefaultFont,(UBYTE *)"Delay DF3:",                NULL},
  314.     {2,1,0,  8, 5,&DefaultFont,(UBYTE *)"Load settings",                NULL},
  315.     {2,1,0,  8, 5,&DefaultFont,(UBYTE *)"Save settings",                NULL},
  316.     {2,1,0, 36, 3,&DefaultFont,(UBYTE *)"Accept",                    NULL},
  317.     {2,1,0, 36, 3,&DefaultFont,(UBYTE *)"Cancel",                    NULL},
  318.     {2,1,0, 13,50,&DefaultFont,(UBYTE *)"The default drive step delay is 3000.",    NULL}
  319. };
  320.  
  321. UBYTE DelayString0[11];
  322. UBYTE UndoDelayString0[11];
  323. UBYTE DelayString1[11];
  324. UBYTE UndoDelayString1[11];
  325. UBYTE DelayString2[11];
  326. UBYTE UndoDelayString2[11];
  327. UBYTE DelayString3[11];
  328. UBYTE UndoDelayString3[11];
  329.  
  330. struct StringInfo DelayStringInfo[4] =
  331. {
  332.     {DelayString0,UndoDelayString0,1,11,11,0,0,0,0,NULL,NULL,NULL},
  333.     {DelayString1,UndoDelayString1,1,11,11,0,0,0,0,NULL,NULL,NULL},
  334.     {DelayString2,UndoDelayString2,1,11,11,0,0,0,0,NULL,NULL,NULL},
  335.     {DelayString3,UndoDelayString3,1,11,11,0,0,0,0,NULL,NULL,NULL}
  336. };
  337.  
  338. SHORT DelayBorderData[] =
  339. {
  340.     -1,-1, 88,-1, 88, 8,-1, 8,-1,-1,
  341.     -2,-1, 89,-1, 89, 8,-2, 8,-2,-1,
  342.     -1,-1, 88,-1, 88, 8,-1, 8,-1,-1,
  343.     -2,-1, 89,-1, 89, 8,-2, 8,-2,-1,
  344.     -1,-1, 88,-1, 88, 8,-1, 8,-1,-1,
  345.     -2,-1, 89,-1, 89, 8,-2, 8,-2,-1,
  346.     -1,-1, 88,-1, 88, 8,-1, 8,-1,-1,
  347.     -2,-1, 89,-1, 89, 8,-2, 8,-2,-1,
  348.     -1,-1,120,-1,120,19,-1,19,-1,-1,
  349.     -2,-1,121,-1,121,19,-2,19,-2,-1,
  350.      1, 1,118, 1,118,17, 1,17, 1, 1,
  351.      2, 1,117, 1,117,17, 2,17, 2, 1,
  352.     -1,-1,120,-1,120,19,-1,19,-1,-1,
  353.     -2,-1,121,-1,121,19,-2,19,-2,-1,
  354.      1, 1,118, 1,118,17, 1,17, 1, 1,
  355.      2, 1,117, 1,117,17, 2,17, 2, 1,
  356.     -1,-1,120,-1,120,14,-1,14,-1,-1,
  357.     -2,-1,121,-1,121,14,-2,14,-2,-1,
  358.      1, 1,118, 1,118,12, 1,12, 1, 1,
  359.      2, 1,117, 1,117,12, 2,12, 2, 1,
  360.     -1,-1,120,-1,120,14,-1,14,-1,-1,
  361.     -2,-1,121,-1,121,14,-2,14,-2,-1,
  362.      1, 1,118, 1,118,12, 1,12, 1, 1,
  363.      2, 1,117, 1,117,12, 2,12, 2, 1,
  364.      0, 0,318, 0,318,77, 0,77, 0, 1,
  365.      0, 0,318, 0,318,77, 0,77, 0, 1
  366. };
  367.  
  368. struct Border DelayBorder[26] =
  369. {
  370.     {0,0,2,0,0,5,&DelayBorderData[  0],&DelayBorder[ 1]},
  371.     {0,0,2,0,0,5,&DelayBorderData[ 10],NULL},
  372.     {0,0,2,0,0,5,&DelayBorderData[ 20],&DelayBorder[ 3]},
  373.     {0,0,2,0,0,5,&DelayBorderData[ 30],NULL},
  374.     {0,0,2,0,0,5,&DelayBorderData[ 40],&DelayBorder[ 5]},
  375.     {0,0,2,0,0,5,&DelayBorderData[ 50],NULL},
  376.     {0,0,2,0,0,5,&DelayBorderData[ 60],&DelayBorder[ 7]},
  377.     {0,0,2,0,0,5,&DelayBorderData[ 70],NULL},
  378.     {0,0,2,0,0,5,&DelayBorderData[ 80],&DelayBorder[ 9]},
  379.     {0,0,2,0,0,5,&DelayBorderData[ 90],&DelayBorder[10]},
  380.     {0,0,2,0,0,5,&DelayBorderData[100],&DelayBorder[11]},
  381.     {0,0,2,0,0,5,&DelayBorderData[110],NULL},
  382.     {0,0,2,0,0,5,&DelayBorderData[120],&DelayBorder[13]},
  383.     {0,0,2,0,0,5,&DelayBorderData[130],&DelayBorder[14]},
  384.     {0,0,2,0,0,5,&DelayBorderData[140],&DelayBorder[15]},
  385.     {0,0,2,0,0,5,&DelayBorderData[150],NULL},
  386.     {0,0,2,0,0,5,&DelayBorderData[160],&DelayBorder[17]},
  387.     {0,0,2,0,0,5,&DelayBorderData[170],&DelayBorder[18]},
  388.     {0,0,2,0,0,5,&DelayBorderData[180],&DelayBorder[19]},
  389.     {0,0,2,0,0,5,&DelayBorderData[190],NULL},
  390.     {0,0,2,0,0,5,&DelayBorderData[200],&DelayBorder[21]},
  391.     {0,0,2,0,0,5,&DelayBorderData[210],&DelayBorder[22]},
  392.     {0,0,2,0,0,5,&DelayBorderData[220],&DelayBorder[23]},
  393.     {0,0,2,0,0,5,&DelayBorderData[230],NULL},
  394.     {2,1,2,0,0,5,&DelayBorderData[240],&DelayBorder[25]},
  395.     {3,1,2,0,0,5,&DelayBorderData[250],NULL}
  396. };
  397.  
  398. struct Gadget DelayGadgets[8] =
  399. {
  400.     {&DelayGadgets[1],    101, 5, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 0],NULL,(APTR)&DelayIntTxt[0],NULL,(APTR)&DelayStringInfo[0],    0,NULL},
  401.     {&DelayGadgets[2],    101,16, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 2],NULL,(APTR)&DelayIntTxt[1],NULL,(APTR)&DelayStringInfo[1],    1,NULL},
  402.     {&DelayGadgets[3],    101,27, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 4],NULL,(APTR)&DelayIntTxt[2],NULL,(APTR)&DelayStringInfo[2],    2,NULL},
  403.     {&DelayGadgets[4],    101,38, 88, 8,0,3075,4100,(APTR)&DelayBorder[ 6],NULL,(APTR)&DelayIntTxt[3],NULL,(APTR)&DelayStringInfo[3],    3,NULL},
  404.     {&DelayGadgets[5],    195, 5,120,19,0,   3,4097,(APTR)&DelayBorder[ 8],NULL,(APTR)&DelayIntTxt[4],NULL,NULL,                4,NULL},
  405.     {&DelayGadgets[6],    195,27,120,19,0,   3,4097,(APTR)&DelayBorder[12],NULL,(APTR)&DelayIntTxt[5],NULL,NULL,                5,NULL},
  406.     {&DelayGadgets[7],     12,61,120,14,0,   3,4097,(APTR)&DelayBorder[16],NULL,(APTR)&DelayIntTxt[6],NULL,NULL,                6,NULL},
  407.     {NULL,            195,61,120,14,0,   3,4097,(APTR)&DelayBorder[20],NULL,(APTR)&DelayIntTxt[7],NULL,NULL,                7,NULL}
  408. };
  409.  
  410. struct Requester DelayReq;
  411.  
  412.     /* A very new window (well, sort of). */
  413.  
  414. struct NewWindow NewWindow =
  415. {
  416.     0,0,
  417.     330,93,
  418.     -1,-1,
  419.     CLOSEWINDOW | GADGETUP | MOUSEBUTTONS | MENUPICK | VANILLAKEY,
  420.     WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | ACTIVATE | RMBTRAP,
  421.     (struct Gadget *)&FormatGadget[0],
  422.     (struct Image *)NULL,
  423.     (STRPTR)"Formatter 2.7",
  424.     (struct Screen *)NULL,
  425.     (struct BitMap *)NULL,
  426.     0,0,
  427.     0,0,
  428.     WBENCHSCREEN
  429. };
  430.  
  431.     /* The track indicator (run dump). */
  432.  
  433. USHORT PanelMap[220] =
  434. {
  435.     0x78F0,0x0000,0x0030,0xF000,0x0000,0x78F0,0x0000,0x0078,
  436.     0xF000,0x0000,0xC0F0,0x0000,0x00FC,0xF000,0x0000,0x78F0,
  437.     0x0000,0x00FC,0xF000,0x0000,0xCD98,0x0000,0x0071,0x9800,
  438.     0x0000,0xCD98,0x0000,0x00CD,0x9800,0x0000,0xD998,0x0000,
  439.     0x00C1,0x9800,0x0000,0xC198,0x0000,0x000D,0x9800,0x0000,
  440.     0xCD98,0x0000,0x0031,0x9800,0x0000,0x1998,0x0000,0x0019,
  441.     0x9800,0x0000,0xD998,0x0000,0x00F9,0x9800,0x0000,0xF998,
  442.     0x0000,0x0019,0x9800,0x0000,0xCD98,0x0000,0x0031,0x9800,
  443.     0x0000,0x3198,0x0000,0x00CD,0x9800,0x0000,0xFD98,0x0000,
  444.     0x000D,0x9800,0x0000,0xCD98,0x0000,0x0031,0x9800,0x0000,
  445.     0x78F0,0x0000,0x0078,0xF000,0x0000,0xFCF0,0x0000,0x0078,
  446.     0xF000,0x0000,0x18F0,0x0000,0x00F8,0xF000,0x0000,0x78F0,
  447.     0x0000,0x0030,0xF000,0x0000,0x0000,0x0000,0x0000,0x0000,
  448.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  449.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  450.     0xC000,0x0000,0x00C0,0x0000,0x0000,0xC000,0x0000,0x00C0,
  451.     0x0000,0x0000,0xC000,0x0000,0x00C0,0x0000,0x0000,0xC000,
  452.     0x0000,0x00C0,0x0000,0x0000,0xC000,0x0000,0x00C0,0x0000,
  453.     0x0000,0xC000,0x0000,0x00C0,0x0000,0x0000,0xC000,0x0000,
  454.     0x00C0,0x0000,0x0000,0xC000,0x0000,0x00C0,0x0000,0x0000,
  455.     0xC000,0x0C00,0x00C0,0x000C,0x0000,0xC000,0x0C00,0x00C0,
  456.     0x000C,0x0000,0xC000,0x0C00,0x00C0,0x000C,0x0000,0xC000,
  457.     0x0C00,0x00C0,0x000C,0x0000,0xC000,0x0C00,0x00C0,0x000C,
  458.     0x0000,0xC000,0x0C00,0x00C0,0x000C,0x0000,0xC000,0x0C00,
  459.     0x00C0,0x000C,0x0000,0xC000,0x0C00,0x00C0,0x000C,0x0000,
  460.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  461.     0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
  462.     0xFFFF,0xFFFF,0xFFFF,0xFFFF
  463. };
  464.  
  465.     /* The track indicator (the image structure). */
  466.  
  467. struct Image PanelImage =
  468. {
  469.     0,0,
  470.     320,11,1,
  471.     (USHORT *)&PanelMap[0],
  472.     0x01,0x00,
  473.     (struct Image *)NULL
  474. };
  475.  
  476.     /* A rectangular shape. */
  477.  
  478. struct Image Box =
  479. {
  480.     0,0,4,12,2,
  481.     (USHORT *)NULL,
  482.     0,0x03,
  483.     (struct Image *)NULL
  484. };
  485.  
  486.     /* A standard disk bootblock (as used by the install command, only the
  487.      * DOS disk ID and the checksum are missing).
  488.      */
  489.  
  490. ULONG Standard[13] =
  491. {
  492.     0x00000000,0x00000000,0x00000370,0x43FA0018,0x4EAEFFA0,0x4A80670A,
  493.     0x20402068,0x00167000,0x4E7570FF,0x60FA646F,0x732E6C69,0x62726172,
  494.     0x79000000
  495. };
  496.  
  497.     /* Some embedded assembly language code. */
  498.  
  499. #asm
  500.     PUBLIC    _Strlen
  501.     PUBLIC    _Strcpy
  502.  
  503. ;    Simple strlen routine.
  504.  
  505. _Strlen:
  506.     MOVEQ    #0,D0        ; Reset length counter
  507. 1$    TST.B    (A0)+        ; Check for end
  508.     BEQ.S    2$        ; Found it
  509.     ADDQ    #1,D0        ; Increment length counter
  510.     BRA.S    1$        ; Test again
  511. 2$    RTS
  512.  
  513. ;    Simple strcpy routine
  514.  
  515. _Strcpy:
  516.     TST.B    (A1)        ; Check source byte
  517.     BEQ.S    1$        ; Found the end?
  518.     MOVE.B    (A1)+,(A0)+    ; Copy the byte over
  519.     BRA.S    _Strcpy        ; Test again
  520. 1$    MOVE.B    #0,(A0)        ; Null termination
  521.     RTS
  522. #endasm
  523.  
  524.     /* FindDevice():
  525.      *
  526.      *    Tries to discover a device name in the linked list
  527.      *    of device nodes to be found in DosLibrary.
  528.      */
  529.  
  530. BYTE
  531. FindDevice(char *DevName)
  532. {
  533.     extern struct DosLibrary    *DOSBase;
  534.     char                *Pointer,Name[257];
  535.     register struct DeviceNode    *DevInfo;
  536.     struct RootNode            *RootNode = (struct RootNode *)DOSBase -> dl_Root;
  537.     SHORT                 i;
  538.  
  539.         /* Knock the rest of the system out. */
  540.  
  541.     Forbid();
  542.  
  543.         /* The starting point. */
  544.  
  545.     DevInfo = (struct DeviceNode *)BADDR(((struct DosInfo *)BADDR(RootNode -> rn_Info)) -> di_DevInfo);
  546.  
  547.         /* As long as it's valid. */
  548.  
  549.     while(DevInfo)
  550.     {
  551.             /* Is it a device and does it have a file handler task attached? */
  552.  
  553.         if(DevInfo -> dn_Type == DLT_DEVICE && DevInfo -> dn_Task)
  554.         {
  555.                 /* Convert the name. */
  556.  
  557.             Pointer = (char *)BADDR(DevInfo -> dn_Name);
  558.  
  559.             for(i = 0 ; i < Pointer[0] ; i++)
  560.                 Name[i] = Pointer[i + 1];
  561.  
  562.             Name[Pointer[0]    ] = ':';
  563.             Name[Pointer[0] + 1] = 0;
  564.  
  565.                 /* Compare the names. */
  566.  
  567.             if(!Strcmp(Name,DevName))
  568.             {
  569.                 Permit();
  570.                 return(TRUE);
  571.             }
  572.         }
  573.  
  574.             /* Check next entry. */
  575.  
  576.         DevInfo = (struct DeviceNode *)BADDR(DevInfo -> dn_Next);
  577.     }
  578.  
  579.     Permit();
  580.  
  581.     return(FALSE);
  582. }
  583.  
  584.     /* RefreshGadget():
  585.      *
  586.      *    Clears the background of a gadget and refreshes it.
  587.      */
  588.  
  589. VOID
  590. RefreshGadget(struct Window *Window,struct Gadget *Gadget,BYTE Colour)
  591. {
  592.     struct Gadget    *NextGadget = Gadget -> NextGadget;
  593.     BYTE         FgPen = Window -> RPort -> FgPen;
  594.  
  595.         /* Clear the background. */
  596.  
  597.     SetAPen(Window -> RPort,Colour);
  598.     RectFill(Window -> RPort,Gadget -> LeftEdge,Gadget -> TopEdge,Gadget -> LeftEdge + Gadget -> Width - 1,Gadget -> TopEdge + Gadget -> Height - 1);
  599.     SetAPen(Window -> RPort,FgPen);
  600.  
  601.         /* Refresh a single gadget. */
  602.  
  603.     Gadget -> NextGadget = NULL;
  604.     RefreshGadgets(Gadget,Window,NULL);
  605.     Gadget -> NextGadget = NextGadget;
  606. }
  607.  
  608.     /* ClearPort():
  609.      *
  610.      *    Removes all pending messages from the Window UserPort.
  611.      */
  612.  
  613. VOID
  614. ClearPort()
  615. {
  616.     while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  617.         ReplyMsg(Massage);
  618.  
  619.     Class    = NULL;
  620.     Code    = NULL;
  621. }
  622.  
  623.     /* PerformRequest():
  624.      *
  625.      *    Display the information requester in the
  626.      *    formatter window.
  627.      */
  628.  
  629. VOID
  630. PerformRequest()
  631. {
  632.     InitRequester(&Req);
  633.  
  634.         /* I don't know how it happened, but the main
  635.          * window is an odd number of rows wide, which
  636.          * makes it somehow difficult to cover the
  637.          * window properly with the requester.
  638.          */
  639.  
  640.     Req . LeftEdge    = 4;
  641.     Req . TopEdge    = 11 + TopEdge;
  642.     Req . Width    = 324;
  643.     Req . Height    = 80;
  644.     Req . BackFill    = 1;
  645.     Req . Flags    = NOISYREQ | SIMPLEREQ;
  646.     Req . ReqGadget    = &ReqGadget;
  647.     Req . ReqBorder    = &ReqBorder[2];
  648.     Req . ReqText    = &ReqIntTxt[1];
  649.  
  650.         /* Now, this gets really boring. */
  651.  
  652.     if(Request(&Req,Window))
  653.     {
  654.         FOREVER
  655.         {
  656.             WaitPort(Window -> UserPort);
  657.  
  658.             while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  659.             {
  660.                 Class = Massage -> Class;
  661.  
  662.                 if(Class == GADGETUP || Class == VANILLAKEY)
  663.                 {
  664.                     EndRequest(&Req,Window);
  665.                     return;
  666.                 }
  667.             }
  668.         }
  669.     }
  670. }
  671.  
  672.     /* SetStepDelays():
  673.      *
  674.      *    Adjusts the step delay for all four disk drives.
  675.      */
  676.  
  677. VOID
  678. SetStepDelays(ULONG *DelayTable)
  679. {
  680.     struct MsgPort        *DelayPort;
  681.     struct IOExtTD        *TDDelayRequest;
  682.     struct TDU_PublicUnit    *PublicUnit;
  683.     SHORT             i;
  684.  
  685.     if(DelayPort = (struct MsgPort *)CreatePort(NULL,0))
  686.     {
  687.         if(TDDelayRequest = (struct IOExtTD *)CreateExtIO(DelayPort,sizeof(struct IOExtTD)))
  688.         {
  689.             Forbid();
  690.  
  691.             for(i = 0 ; i < 4 ; i++)
  692.             {
  693.                 if(DelayTable[i])
  694.                 {
  695.                     if(!OpenDevice(TD_NAME,i,TDDelayRequest,0))
  696.                     {
  697.                         PublicUnit = (struct TDU_PublicUnit *)TDDelayRequest -> iotd_Req . io_Unit;
  698.  
  699.                         PublicUnit -> tdu_StepDelay = DelayTable[i];
  700.  
  701.                         CloseDevice(TDDelayRequest);
  702.                     }
  703.                 }
  704.             }
  705.  
  706.             Permit();
  707.  
  708.             for(i = 0 ; i < 4 ; i++)
  709.                 DelayStringInfo[i] . LongInt = DelayTable[i];
  710.  
  711.             SPrintf((char *)DelayString0,"%ld",DelayStringInfo[0] . LongInt);
  712.             SPrintf((char *)DelayString1,"%ld",DelayStringInfo[1] . LongInt);
  713.             SPrintf((char *)DelayString2,"%ld",DelayStringInfo[2] . LongInt);
  714.             SPrintf((char *)DelayString3,"%ld",DelayStringInfo[3] . LongInt);
  715.  
  716.             Strcpy(UndoDelayString0,DelayString0);
  717.             Strcpy(UndoDelayString1,DelayString1);
  718.             Strcpy(UndoDelayString2,DelayString2);
  719.             Strcpy(UndoDelayString3,DelayString3);
  720.  
  721.             DeleteExtIO(TDDelayRequest);
  722.         }
  723.  
  724.         DeletePort(DelayPort);
  725.     }
  726. }
  727.  
  728.     /* PerformDelayRequest():
  729.      *
  730.      *    This requester helps the user to adjust the step
  731.      *    delay of all four disk drives.
  732.      */
  733.  
  734. VOID
  735. PerformDelayRequest()
  736. {
  737.     SHORT    i;
  738.     USHORT    ID;
  739.     ULONG    DelayTable[4],OldDelayTable[4];
  740.  
  741.     for(i = 0 ; i < 4 ; i++)
  742.         OldDelayTable[i] = DelayStringInfo[i] . LongInt;
  743.  
  744.     InitRequester(&DelayReq);
  745.  
  746.         /* I don't know how it happened, but the main
  747.          * window is an odd number of rows wide, which
  748.          * makes it somehow difficult to cover the
  749.          * window properly with the requester.
  750.          */
  751.  
  752.     DelayReq . LeftEdge        = 4;
  753.     DelayReq . TopEdge        = 11 + TopEdge;
  754.     DelayReq . Width        = 324;
  755.     DelayReq . Height        = 80;
  756.     DelayReq . BackFill        = 1;
  757.     DelayReq . Flags        = SIMPLEREQ;
  758.     DelayReq . ReqGadget        = &DelayGadgets[0];
  759.     DelayReq . ReqBorder        = &DelayBorder[24];
  760.     DelayReq . ReqText        = &DelayIntTxt[8];
  761.  
  762.         /* Now, this gets really boring. */
  763.  
  764.     if(Request(&DelayReq,Window))
  765.     {
  766.         FOREVER
  767.         {
  768.             WaitPort(Window -> UserPort);
  769.  
  770.             while(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  771.             {
  772.                 Class    = Massage -> Class;
  773.                 ID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  774.  
  775.                 if(Class == GADGETUP)
  776.                 {
  777.                     switch(ID)
  778.                     {
  779.                         /* Drives. */
  780.  
  781.                         case 0:
  782.                         case 1:
  783.                         case 2:
  784.                         case 3:    break;
  785.  
  786.                         /* Load settings. */
  787.  
  788.                         case 4:    if(!DelayFileReq)
  789.                             {
  790.                                 if(DelayFileReq = ArpAllocFreq())
  791.                                 {
  792.                                     Strcpy(DelayFileReq -> fr_File,"Formatter_Steps");
  793.                                     Strcpy(DelayFileReq -> fr_Dir,"S:");
  794.                                 }
  795.                             }
  796.  
  797.                             if(DelayFileReq)
  798.                             {
  799.                                 DelayFileReq -> fr_Hail = "Load settings";
  800.  
  801.                                 while(FileRequest(DelayFileReq))
  802.                                 {
  803.                                     BPTR    Handle;
  804.                                     char    Name[DSIZE * 5 + FCHARS];
  805.                                     ULONG    TempDelay[4];
  806.  
  807.                                     Strcpy(Name,DelayFileReq -> fr_Dir);
  808.                                     TackOn(Name,DelayFileReq -> fr_File);
  809.  
  810.                                     if(Handle = Open(Name,MODE_OLDFILE))
  811.                                     {
  812.                                         if(Read(Handle,TempDelay,4 * sizeof(ULONG)) == 4 * sizeof(ULONG))
  813.                                         {
  814.                                             for(i = 0 ; i < 4 ; i++)
  815.                                                 DelayStringInfo[i] . LongInt = TempDelay[i];
  816.  
  817.                                             SPrintf((char *)DelayString0,"%ld",DelayStringInfo[0] . LongInt);
  818.                                             SPrintf((char *)DelayString1,"%ld",DelayStringInfo[1] . LongInt);
  819.                                             SPrintf((char *)DelayString2,"%ld",DelayStringInfo[2] . LongInt);
  820.                                             SPrintf((char *)DelayString3,"%ld",DelayStringInfo[3] . LongInt);
  821.  
  822.                                             Strcpy(UndoDelayString0,DelayString0);
  823.                                             Strcpy(UndoDelayString1,DelayString1);
  824.                                             Strcpy(UndoDelayString2,DelayString2);
  825.                                             Strcpy(UndoDelayString3,DelayString3);
  826.  
  827.                                             RefreshGadgets(&DelayGadgets[0],Window,&DelayReq);
  828.  
  829.                                             Close(Handle);
  830.  
  831.                                             break;
  832.                                         }
  833.  
  834.                                         Close(Handle);
  835.                                     }
  836.  
  837.                                     DisplayBeep(Window -> WScreen);
  838.                                 }
  839.                             }
  840.                                     
  841.                             break;
  842.  
  843.                         /* Save settings. */
  844.  
  845.                         case 5:    if(!DelayFileReq)
  846.                             {
  847.                                 if(DelayFileReq = ArpAllocFreq())
  848.                                 {
  849.                                     Strcpy(DelayFileReq -> fr_File,"Formatter_Steps");
  850.                                     Strcpy(DelayFileReq -> fr_Dir,"S:");
  851.                                 }
  852.                             }
  853.  
  854.                             if(DelayFileReq)
  855.                             {
  856.                                 ULONG    TempDelay[4];
  857.  
  858.                                 DelayFileReq -> fr_Hail = "Save settings";
  859.  
  860.                                 for(i = 0 ; i < 4 ; i++)
  861.                                     TempDelay[i] = DelayStringInfo[i] . LongInt;
  862.  
  863.                                 while(FileRequest(DelayFileReq))
  864.                                 {
  865.                                     BPTR    Handle;
  866.                                     char    Name[DSIZE * 5 + FCHARS];
  867.  
  868.                                     Strcpy(Name,DelayFileReq -> fr_Dir);
  869.                                     TackOn(Name,DelayFileReq -> fr_File);
  870.  
  871.                                     if(Handle = Open(Name,MODE_NEWFILE))
  872.                                     {
  873.                                         if(Write(Handle,TempDelay,4 * sizeof(ULONG)) == 4 * sizeof(ULONG))
  874.                                         {
  875.                                             Close(Handle);
  876.  
  877.                                             break;
  878.                                         }
  879.  
  880.                                         Close(Handle);
  881.                                     }
  882.  
  883.                                     DisplayBeep(Window -> WScreen);
  884.                                 }
  885.                             }
  886.                                     
  887.                             break;
  888.  
  889.                         /* Accept. */
  890.  
  891.                         case 6:    for(i = 0 ; i < 4 ; i++)
  892.                                 DelayTable[i] = DelayStringInfo[i] . LongInt;
  893.  
  894.                             SetStepDelays(DelayTable);
  895.  
  896.                             EndRequest(&DelayReq,Window);
  897.                             return;
  898.  
  899.                         /* Cancel. */
  900.  
  901.                         case 7:    EndRequest(&DelayReq,Window);
  902.  
  903.                             SetStepDelays(OldDelayTable);
  904.  
  905.                             return;
  906.                     }
  907.                 }
  908.             }
  909.         }
  910.     }
  911. }
  912.  
  913.     /* AdjustClass():
  914.      *
  915.      *    Formatter is controlled both by menu and by gadgets;
  916.      *    the following routine links both interfaces.
  917.      */
  918.  
  919. VOID
  920. AdjustClass()
  921. {
  922.     USHORT MenuNum = Code;
  923.  
  924.         /* Truly selected a menu item? */
  925.  
  926.     if(MenuNum != MENUNULL)
  927.     {
  928.         BYTE i;
  929.  
  930.         Class = GADGETUP;
  931.  
  932.             /* Get the menu item behind the Intuition menu number. */
  933.  
  934.         while(MenuNum != MENUNULL)
  935.         {
  936.             if(MENUNUM(MenuNum) == 0)
  937.             {
  938.                 switch(ITEMNUM(MenuNum))
  939.                 {
  940.                     case 0:    PerformRequest();
  941.                         Class = NULL;
  942.                         break;
  943.  
  944.                     case 2:    FormatGadget[4] . Flags ^= SELECTED;
  945.                         RefreshGadget(Window,&FormatGadget[4],0);
  946.                         Class = NULL;
  947.                         break;
  948.  
  949.                     case 3:    FormatGadget[6] . Flags ^= SELECTED;
  950.                         RefreshGadget(Window,&FormatGadget[6],0);
  951.                         Class = NULL;
  952.                         break;
  953.  
  954.                     case 4:    FormatGadget[5] . Flags ^= SELECTED;
  955.                         RefreshGadget(Window,&FormatGadget[5],0);
  956.                         Class = NULL;
  957.                         break;
  958.  
  959.                     case 5:    FormatGadget[7] . Flags ^= SELECTED;
  960.                         RefreshGadget(Window,&FormatGadget[7],0);
  961.                         Class = NULL;
  962.                         break;
  963.  
  964.                     case 8:
  965.                     case 9:
  966.                     case 10:
  967.                     case 11:for(i = 0 ; i < 4 ; i++)
  968.                             if((FormatMenuItem[8 + i] . Flags & ITEMENABLED) && 8 + i != ITEMNUM(MenuNum))
  969.                                 FormatMenuItem[8 + i] . Flags &= ~CHECKED;
  970.  
  971.                         GadgetID = ITEMNUM(MenuNum) - 8;
  972.                         break;
  973.  
  974.                     case 13:PerformDelayRequest();
  975.                         Class = NULL;
  976.                         break;
  977.  
  978.                     case 14:GadgetID = 8;
  979.                         break;
  980.  
  981.                     case 16:Class = CLOSEWINDOW;
  982.                         break;
  983.  
  984.                     default:Class = NULL;
  985.                         break;
  986.                 }
  987.             }
  988.  
  989.             MenuNum = ((struct MenuItem *)ItemAddress(&FormatMenu,MenuNum)) -> NextSelect;
  990.         }
  991.     }
  992. }
  993.  
  994.     /* ConvertString():
  995.      *
  996.      *    Turn a 'C' string into a BCPL string.
  997.      */
  998.  
  999. VOID
  1000. ConvertString(char *ToString,char *FromString)
  1001. {
  1002.     *ToString++ = Strlen(FromString);
  1003.  
  1004.     while(*FromString)
  1005.         *ToString++ = *FromString++;
  1006. }
  1007.  
  1008.     /* FixBlockSum():
  1009.      *
  1010.      *    Calculate the checksum for a DOS disk block.
  1011.      *    The checksum itself is the complement of the sum
  1012.      *    of all the longwords contained in a track.
  1013.      */
  1014.  
  1015. ULONG
  1016. FixBlockSum(ULONG *Array)
  1017. {
  1018.     ULONG    Sum = 0;
  1019.     UBYTE    i = 128;
  1020.  
  1021.     while(i--)
  1022.         Sum += Array[i];
  1023.  
  1024.     return(-Sum);
  1025. }
  1026.  
  1027.     /* FixBootSum(ULONG *Array):
  1028.      *
  1029.      *    Calculates the checksum for a disk bootblock, which
  1030.      *    unfortunately uses an algorithm different from
  1031.      *    FixBlockSum.
  1032.      */
  1033.  
  1034. ULONG
  1035. FixBootSum(ULONG *Array)
  1036. {
  1037.     ULONG    Sum = 0,LastSum;
  1038.     UBYTE    i = 128;
  1039.  
  1040.     while(i--)
  1041.     {
  1042.         LastSum = Sum;
  1043.  
  1044.         if((Sum += Array[i]) < LastSum)
  1045.             Sum++;
  1046.     }
  1047.  
  1048.     return(~Sum);
  1049. }
  1050.  
  1051.     /* SetBitmapBlock():
  1052.      *
  1053.      *    Marks a block in the disk bitmap (bit by bit).
  1054.      *    A standard bitmap consists of fifty-five longwords
  1055.      *    in which each bit represents a disk block. If a
  1056.      *    bit is set, a block is unused. A cleared bit indicates
  1057.      *    an allocated block.
  1058.      */
  1059.  
  1060. VOID
  1061. SetBitmapBlock(ULONG *BitmapData,SHORT Block,BYTE SetFlag)
  1062. {
  1063.     if(SetFlag)
  1064.         BitmapData[Block / 32] &= ~(1 << (Block % 32));
  1065.     else
  1066.         BitmapData[Block / 32] |=  (1 << (Block % 32));
  1067. }
  1068.  
  1069.     /* ClearBlock():
  1070.      *
  1071.      *    Set the contents of disk block to zero. It takes less
  1072.      *    time to clear the longwords contained in a disk track
  1073.      *    than to clear the single bytes.
  1074.      */
  1075.  
  1076. VOID
  1077. ClearBlock(ULONG *Block)
  1078. {
  1079.     UBYTE Offset = 128;
  1080.  
  1081.     while(Offset--)
  1082.         *Block++ = 0;
  1083. }
  1084.  
  1085.     /* Inhibit():
  1086.      *
  1087.      *    Toggle the activity of the disk validator. We send
  1088.      *    a DOS packet to the file handler task telling it
  1089.      *    to disable or to enable the disk validator.
  1090.      */
  1091.  
  1092. VOID
  1093. Inhibit(char *Drive,BYTE Bool)
  1094. {
  1095.     struct MsgPort    *Handler;
  1096.     LONG         Args[7];
  1097.  
  1098.     if(Bool)
  1099.         Args[0] = DOSTRUE;
  1100.     else
  1101.         Args[0] = DOSFALSE;
  1102.  
  1103.     if(Handler = DeviceProc(Drive))
  1104.         SendPacket(ACTION_INHIBIT,Args,Handler);
  1105. }
  1106.  
  1107.     /* CompareTracks():
  1108.      *
  1109.      *    Check if two disk blocks are equal.
  1110.      */
  1111.  
  1112. BYTE
  1113. CompareTracks(ULONG *Track1,ULONG *Track2)
  1114. {
  1115.     BYTE Result;
  1116.  
  1117.         /* Allocate the blitter for private use. */
  1118.  
  1119.     OwnBlitter();
  1120.     WaitBlit();
  1121.  
  1122.         /* Set the blitter data addresses. We will use
  1123.          * sources A & C.
  1124.          */
  1125.  
  1126.     custom . bltapt        = (APTR)Track1;
  1127.     custom . bltcpt        = (APTR)Track2;
  1128.  
  1129.         /* The blitter modulo values are not important
  1130.          * in this example.
  1131.          */
  1132.  
  1133.     custom . bltamod    = 0;
  1134.     custom . bltcmod    = 0;
  1135.  
  1136.         /* Set the first and last word mask values. */
  1137.  
  1138.     custom . bltafwm    = 0xFFFF;
  1139.     custom . bltalwm    = 0xFFFF;
  1140.  
  1141.         /* Set the blitter control registers.
  1142.          * We will work with sources A & C. The
  1143.          * minterm A_XOR_C will cause the blitter to
  1144.          * generate zeroes if both sources are
  1145.          * equal.
  1146.          */
  1147.  
  1148.     custom . bltcon0    = SRCA | SRCC | A_XOR_C;
  1149.     custom . bltcon1    = 0;
  1150.  
  1151.         /* This last assignment starts the blitter.
  1152.          * The size of a disk track is 11264 bytes,
  1153.          * in other words, 64 x 176 bytes.
  1154.          */
  1155.  
  1156. /*    custom . bltsize    = (((176 & VSIZEMASK) << 6 ) | ((64 >> 1) & HSIZEMASK));*/
  1157.     custom . bltsize    = 0x2C20;
  1158.  
  1159.     WaitBlit();
  1160.  
  1161.         /* If both sources are equal zeroes will have
  1162.          * been generated, i.e. the blitter zero
  1163.          * flag will be set.
  1164.          */
  1165.  
  1166.     if(custom . dmaconr & DMAF_BLTNZERO)
  1167.         Result = TRUE;
  1168.     else
  1169.         Result = FALSE;
  1170.  
  1171.     DisownBlitter();
  1172.  
  1173.     return(Result);
  1174. }
  1175.  
  1176.     /* DiskRead():
  1177.      *
  1178.      *    Read a track from disk and compare it with the
  1179.      *    data in the buffer.
  1180.      */
  1181.  
  1182. BYTE
  1183. DiskRead(BYTE Track)
  1184. {
  1185.     SHORT    Position = 4 + Box . Width * Track;
  1186.     BYTE    Error;
  1187.  
  1188.         /* Initialize the request. */
  1189.  
  1190.     DiskRequest -> iotd_Req . io_Offset = OffsetTable[Track];
  1191.  
  1192.         /* Start the request. */
  1193.  
  1194.     BeginIO(DiskRequest);
  1195.  
  1196.         /* Move up one track. */
  1197.  
  1198.     Box . PlaneOnOff = 3;
  1199.     DrawImage(Window -> RPort,&Box,Position,23 + TopEdge);
  1200.  
  1201.         /* News in the mail? */
  1202.  
  1203.     if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1204.     {
  1205.         Class        = Massage -> Class;
  1206.         Code        = Massage -> Code;
  1207.         GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  1208.  
  1209.         ReplyMsg(Massage);
  1210.  
  1211.         if(Class == MENUPICK)
  1212.             AdjustClass();
  1213.  
  1214.         if(Class == GADGETUP)
  1215.         {
  1216.                 /* Stop formatting? */
  1217.  
  1218.             if(GadgetID == 8)
  1219.             {
  1220.                 /* Wait for request to be replied. */
  1221.  
  1222.                 WaitIO(DiskRequest);
  1223.  
  1224.                 /* Format aborted. */
  1225.  
  1226.                 return(-42);
  1227.             }
  1228.  
  1229.             if(GadgetID == 4)
  1230.                 FormatMenuItem[2] . Flags ^= CHECKED;
  1231.  
  1232.             if(GadgetID == 6)
  1233.                 FormatMenuItem[3] . Flags ^= CHECKED;
  1234.  
  1235.             if(GadgetID == 5)
  1236.                 FormatMenuItem[4] . Flags ^= CHECKED;
  1237.  
  1238.             if(GadgetID == 7)
  1239.                 FormatMenuItem[5] . Flags ^= CHECKED;
  1240.         }
  1241.     }
  1242.  
  1243.         /* Trouble? */
  1244.  
  1245.     if(Error = WaitIO(DiskRequest))
  1246.         return(Error);
  1247.  
  1248.         /* Are both buffers equal? */
  1249.  
  1250.     if(Track == 40)
  1251.     {
  1252.         if(!CompareTracks(DiskTrack,RootTrack))
  1253.         {
  1254.             Box . PlaneOnOff = 2;
  1255.             DrawImage(Window -> RPort,&Box,Position,23 + TopEdge);
  1256.  
  1257.             if(DebugFlag)
  1258.             {
  1259.                 char HelpName[20];
  1260.                 BPTR Help;
  1261.  
  1262.                 SPrintf(HelpName,"RAM:SRCTRACK%02ld",Track);
  1263.  
  1264.                 if(Help = Open(HelpName,MODE_NEWFILE))
  1265.                 {
  1266.                     Write(Help,RootTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1267.                     Close(Help);
  1268.                 }
  1269.  
  1270.                 SPrintf(HelpName,"RAM:DSTTRACK%02ld",Track);
  1271.  
  1272.                 if(Help = Open(HelpName,MODE_NEWFILE))
  1273.                 {
  1274.                     Write(Help,DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1275.                     Close(Help);
  1276.                 }
  1277.             }
  1278.  
  1279.             /* Verification error. */
  1280.  
  1281.             return(-43);
  1282.         }
  1283.     }
  1284.     else
  1285.     {
  1286.         if(!CompareTracks(DiskTrack,CheckTrack))
  1287.         {
  1288.             Box . PlaneOnOff = 2;
  1289.             DrawImage(Window -> RPort,&Box,Position,23 + TopEdge);
  1290.  
  1291.             /* Verification error. */
  1292.  
  1293.             if(DebugFlag)
  1294.             {
  1295.                 char HelpName[20];
  1296.                 BPTR Help;
  1297.  
  1298.                 SPrintf(HelpName,"RAM:SRCTRACK%02ld",Track);
  1299.  
  1300.                 if(Help = Open(HelpName,MODE_NEWFILE))
  1301.                 {
  1302.                     Write(Help,CheckTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1303.                     Close(Help);
  1304.                 }
  1305.  
  1306.                 SPrintf(HelpName,"RAM:DSTTRACK%02ld",Track);
  1307.  
  1308.                 if(Help = Open(HelpName,MODE_NEWFILE))
  1309.                 {
  1310.                     Write(Help,DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1311.                     Close(Help);
  1312.                 }
  1313.             }
  1314.  
  1315.             return(-43);
  1316.         }
  1317.     }
  1318.  
  1319.     return(0);
  1320. }
  1321.  
  1322.     /* DiskWrite():
  1323.      *
  1324.      *    Write two blocks to disk.
  1325.      */
  1326.  
  1327. BYTE
  1328. DiskWrite(ULONG Offset,BYTE Track)
  1329. {
  1330.     SHORT     Position = 4 + Box . Width * Track;
  1331.     ULONG    *OriginalTrack = DiskRequest -> iotd_Req . io_Data;
  1332.     BYTE     Error;
  1333.  
  1334.         /* Initialize the request. */
  1335.  
  1336.     DiskRequest -> iotd_Req . io_Command    = ETD_WRITE;
  1337.     DiskRequest -> iotd_Req . io_Length    = TD_SECTOR * 2;
  1338.     DiskRequest -> iotd_Req . io_Offset    = Offset;
  1339.  
  1340.         /* Start the request. */
  1341.  
  1342.     BeginIO(DiskRequest);
  1343.  
  1344.         /* Move up one track. */
  1345.  
  1346.     Box . PlaneOnOff = 1;
  1347.     DrawImage(Window -> RPort,&Box,Position,23 + TopEdge);
  1348.  
  1349.         /* News in the mail? */
  1350.  
  1351.     if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1352.     {
  1353.         Class        = Massage -> Class;
  1354.         Code        = Massage -> Code;
  1355.         GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  1356.  
  1357.         ReplyMsg(Massage);
  1358.  
  1359.         if(Class == MENUPICK)
  1360.             AdjustClass();
  1361.  
  1362.         if(Class == GADGETUP)
  1363.         {
  1364.                 /* Stop formatting? */
  1365.  
  1366.             if(GadgetID == 8)
  1367.             {
  1368.                 /* Wait for request to be replied. */
  1369.  
  1370.                 WaitIO(DiskRequest);
  1371.  
  1372.                 /* Format aborted. */
  1373.  
  1374.                 return(-42);
  1375.             }
  1376.  
  1377.             if(GadgetID == 4)
  1378.                 FormatMenuItem[2] . Flags ^= CHECKED;
  1379.  
  1380.             if(GadgetID == 6)
  1381.                 FormatMenuItem[3] . Flags ^= CHECKED;
  1382.  
  1383.             if(GadgetID == 5)
  1384.                 FormatMenuItem[4] . Flags ^= CHECKED;
  1385.  
  1386.             if(GadgetID == 7)
  1387.                 FormatMenuItem[5] . Flags ^= CHECKED;
  1388.         }
  1389.     }
  1390.  
  1391.         /* Trouble? */
  1392.  
  1393.     if(Error = WaitIO(DiskRequest))
  1394.         return(Error);
  1395.  
  1396.         /* Verify the data? */
  1397.  
  1398.     if(Verify)
  1399.     {
  1400.             /* Make sure the buffer has been written. */
  1401.  
  1402.         DiskRequest -> iotd_Req . io_Command = ETD_UPDATE;
  1403.         DoIO(DiskRequest);
  1404.  
  1405.             /* Reread the buffer. */
  1406.  
  1407.         DiskRequest -> iotd_Req . io_Command    = ETD_READ;
  1408.         DiskRequest -> iotd_Req . io_Data    = (APTR)CheckTrack;
  1409.  
  1410.         if(Error = DoIO(DiskRequest))
  1411.             return(Error);
  1412.  
  1413.             /* Are both buffers equal? */
  1414.  
  1415.         if(!CompareTracks(OriginalTrack,CheckTrack))
  1416.         {
  1417.             Box . PlaneOnOff = 2;
  1418.             DrawImage(Window -> RPort,&Box,Position,23 + TopEdge);
  1419.  
  1420.             /* Verification error. */
  1421.  
  1422.             return(-43);
  1423.         }
  1424.  
  1425.         Box . PlaneOnOff = 3;
  1426.         DrawImage(Window -> RPort,&Box,Position,23 + TopEdge);
  1427.     }
  1428.  
  1429.     return(0);
  1430. }
  1431.  
  1432.     /* DiskFormat():
  1433.      *
  1434.      *    Perform a disk write access.
  1435.      */
  1436.  
  1437. BYTE
  1438. DiskFormat(BYTE Track)
  1439. {
  1440.     BYTE Error;
  1441.  
  1442.         /* Initialize the request. */
  1443.  
  1444.     DiskRequest -> iotd_Req . io_Offset = OffsetTable[Track];
  1445.  
  1446.         /* Install the sector label information. */
  1447.  
  1448.     DiskRequest -> iotd_SecLabel = (ULONG)SectorLabel;
  1449.  
  1450.     if(Track == 40)
  1451.         DiskRequest -> iotd_Req . io_Data = (APTR)RootTrack;
  1452.  
  1453.         /* Start the request. */
  1454.  
  1455.     BeginIO(DiskRequest);
  1456.  
  1457.         /* Move up one track. */
  1458.  
  1459.     Box . PlaneOnOff = 1;
  1460.     DrawImage(Window -> RPort,&Box,4 + Box . Width * Track,23 + TopEdge);
  1461.  
  1462.         /* News in the mail? */
  1463.  
  1464.     if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1465.     {
  1466.         Class        = Massage -> Class;
  1467.         Code        = Massage -> Code;
  1468.         GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  1469.  
  1470.         ReplyMsg(Massage);
  1471.  
  1472.         if(Class == MENUPICK)
  1473.             AdjustClass();
  1474.  
  1475.         if(Class == GADGETUP)
  1476.         {
  1477.                 /* Stop formatting? */
  1478.  
  1479.             if(GadgetID == 8)
  1480.             {
  1481.                 /* Wait for request to be replied. */
  1482.  
  1483.                 WaitIO(DiskRequest);
  1484.  
  1485.                 if(Track == 40)
  1486.                     DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack;
  1487.  
  1488.                 /* Format aborted. */
  1489.  
  1490.                 DiskRequest -> iotd_SecLabel = NULL;
  1491.  
  1492.                 return(-42);
  1493.             }
  1494.  
  1495.             if(GadgetID == 4)
  1496.                 FormatMenuItem[2] . Flags ^= CHECKED;
  1497.  
  1498.             if(GadgetID == 6)
  1499.                 FormatMenuItem[3] . Flags ^= CHECKED;
  1500.  
  1501.             if(GadgetID == 5)
  1502.                 FormatMenuItem[4] . Flags ^= CHECKED;
  1503.  
  1504.             if(GadgetID == 7)
  1505.                 FormatMenuItem[5] . Flags ^= CHECKED;
  1506.         }
  1507.     }
  1508.  
  1509.     Error = WaitIO(DiskRequest);
  1510.  
  1511.     if(Track == 40)
  1512.         DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack;
  1513.  
  1514.     DiskRequest -> iotd_SecLabel = NULL;
  1515.  
  1516.     return(Error);
  1517. }
  1518.  
  1519.     /* Formatter():
  1520.      *
  1521.      *    Format a disk drive, 3½" hardwired to the Amiga.
  1522.      */
  1523.  
  1524. BYTE
  1525. Formatter(char *DiskName)
  1526. {
  1527.     struct DosDirectory    *RootBlock;
  1528.     struct DosBitmap    *DosBitmap;
  1529.     BYTE             Error,GeneralError = FALSE;
  1530.     SHORT             i,Count = 0;
  1531.  
  1532.         /* Allocate both auxilary buffers. */
  1533.  
  1534.     if(CheckTrack = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_SECTOR,MEMF_CHIP | MEMF_CLEAR))
  1535.     {
  1536.         if(DiskTrack = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_SECTOR,MEMF_CHIP | MEMF_CLEAR))
  1537.         {
  1538.             if(RootTrack = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_SECTOR,MEMF_CHIP | MEMF_CLEAR))
  1539.             {
  1540.                 if(SectorLabel = (ULONG *)AllocMem(NUMSECS * NUMHEADS * TD_LABELSIZE,MEMF_CHIP | MEMF_CLEAR))
  1541.                 {
  1542.                         /* It's a DOS disk. */
  1543.  
  1544.                     if(FFS)
  1545.                         CheckTrack[0] = DiskTrack[0] = ID_FFS_DISK;
  1546.                     else
  1547.                         CheckTrack[0] = DiskTrack[0] = ID_DOS_DISK;
  1548.  
  1549.                         /* Tie them to the buffer. */
  1550.  
  1551.                     RootBlock    = (struct DosDirectory *)RootTrack;
  1552.                     DosBitmap    = (struct DosBitmap *)((ULONG)RootTrack + TD_SECTOR);
  1553.  
  1554.                         /* Clear the root block. */
  1555.  
  1556.                     ClearBlock((ULONG *)RootBlock);
  1557.  
  1558.                         /* Initialize the defaults. */
  1559.  
  1560.                     RootBlock -> PrimaryType    = T_SHORT;
  1561.                     RootBlock -> SecondaryType    = ST_ROOT;
  1562.                     RootBlock -> HashTableSize    = 128 - 56;
  1563.                     RootBlock -> BitmapFlag        = DOSFALSE;
  1564.                     RootBlock -> BitmapPointers[0]    = (NUMTRACKS / 2) * NUMSECS + 1;
  1565.  
  1566.                         /* Set the date stamps. */
  1567.  
  1568.                     DateStamp(&RootBlock -> LastRootChange);
  1569.                     DateStamp(&RootBlock -> LastDiskChange);
  1570.                     DateStamp(&RootBlock -> CreationDate);
  1571.  
  1572.                         /* Copy the name string over. */
  1573.  
  1574.                     ConvertString(RootBlock -> DiskName,DiskName);
  1575.  
  1576.                         /* Calculate the block checksum. */
  1577.  
  1578.                     RootBlock -> CheckSum = FixBlockSum((ULONG *)RootBlock);
  1579.  
  1580.                         /* Clear the disk bitmap. */
  1581.  
  1582.                     ClearBlock((ULONG *)DosBitmap);
  1583.  
  1584.                         /* Mark all bitmap blocks as unused. */
  1585.  
  1586.                     for(i = 0 ; i < 55 ; i++)
  1587.                         DosBitmap -> BitmapData[i] = ~0L;
  1588.  
  1589.                         /* Mark two blocks as used (880 -> Root block, 881 -> Bitmap).
  1590.                          * Note that the first two blocks by default are reserved
  1591.                          * and, not being part of the bitmap itself, have to
  1592.                          * be skipped.
  1593.                          */
  1594.  
  1595.                     SetBitmapBlock(DosBitmap -> BitmapData,880 - 2,TRUE);
  1596.                     SetBitmapBlock(DosBitmap -> BitmapData,881 - 2,TRUE);
  1597.  
  1598.                         /* Calculate the block checksum. */
  1599.  
  1600.                     DosBitmap -> CheckSum = FixBlockSum((ULONG *)DosBitmap);
  1601.  
  1602.                         /* Is there a disk in the drive? */
  1603.  
  1604.                     DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
  1605.                     DoIO(DiskRequest);
  1606.  
  1607.                     if(!DiskRequest -> iotd_Req . io_Actual)
  1608.                     {
  1609.                             /* Is the disk write enabled? */
  1610.  
  1611.                         DiskRequest -> iotd_Req . io_Command = TD_PROTSTATUS;
  1612.                         DoIO(DiskRequest);
  1613.  
  1614.                         if(!DiskRequest -> iotd_Req . io_Actual)
  1615.                         {
  1616.                                 /* Get the disk change number. */
  1617.  
  1618.                             DiskRequest -> iotd_Req . io_Command = TD_CHANGENUM;
  1619.                             DoIO(DiskRequest);
  1620.  
  1621.                                 /* Set the standard flags. */
  1622.  
  1623.                             DiskRequest -> iotd_Req . io_Flags    = 0;
  1624.                             DiskRequest -> iotd_Count        = DiskRequest -> iotd_Req . io_Actual;
  1625.  
  1626.                                 /* Remove all messages. */
  1627.  
  1628.                             ClearPort();
  1629.  
  1630.                             if(AutoStart)
  1631.                             {
  1632.                                 DiskRequest -> iotd_Req . io_Command    = ETD_READ;
  1633.                                 DiskRequest -> iotd_Req . io_Data    = (APTR)DiskTrack;
  1634.                                 DiskRequest -> iotd_Req . io_Length    = NUMSECS * NUMHEADS * TD_SECTOR;
  1635.                                 DiskRequest -> iotd_Req . io_Offset    = OffsetTable[40];
  1636.  
  1637.                                 if(!DoIO(DiskRequest))
  1638.                                 {
  1639.                                     if(!FixBlockSum((ULONG *)DiskTrack))
  1640.                                     {
  1641.                                         CopyMem(&((struct DosDirectory *)DiskTrack) -> DiskName[1],InfoText . IText,32);
  1642.  
  1643.                                         InfoText . IText[((struct DosDirectory *)DiskTrack) -> DiskName[0]] = 0;
  1644.  
  1645.                                         InfoText . LeftEdge = 4 + (320 - 8 * Strlen(InfoText . IText)) / 2;
  1646.  
  1647.                                         InfoText . FrontPen = 3;
  1648.                                         PrintIText(Window -> RPort,&InfoText,0,TopEdge);
  1649.                                         InfoText . FrontPen = 1;
  1650.  
  1651.                                         DisplayBeep(Window -> WScreen);
  1652.  
  1653.                                         FOREVER
  1654.                                         {
  1655.                                             if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  1656.                                             {
  1657.                                                 Class        = Massage -> Class;
  1658.                                                 Code        = Massage -> Code;
  1659.                                                 GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  1660.  
  1661.                                                 ReplyMsg(Massage);
  1662.  
  1663.                                                 if(Class == MENUPICK)
  1664.                                                     AdjustClass();
  1665.  
  1666.                                                 if(Class == GADGETUP)
  1667.                                                 {
  1668.                                                         /* Stop formatting? */
  1669.  
  1670.                                                     if(GadgetID == 8)
  1671.                                                     {
  1672.                                                         Error = -42;
  1673.  
  1674.                                                         goto WriteError;
  1675.                                                     }
  1676.                                                 }
  1677.                                             }
  1678.  
  1679.                                             if((Count++) == 6)
  1680.                                                 break;
  1681.  
  1682.                                             Delay(TICKS_PER_SECOND >> 1);
  1683.                                         }
  1684.  
  1685.                                         SetAPen(Window -> RPort,0);
  1686.                                         RectFill(Window -> RPort,4,23 + TopEdge,323,34 + TopEdge);
  1687.                                         SetAPen(Window -> RPort,1);
  1688.                                     }
  1689.                                 }
  1690.  
  1691.                                 CopyMemQuick(CheckTrack,DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1692.                             }
  1693.  
  1694.                                 /* Are we to format the whole disk? */
  1695.  
  1696.                             if(!Fast)
  1697.                             {
  1698.                                 DiskRequest -> iotd_Req . io_Command    = ETD_FORMAT;
  1699.                                 DiskRequest -> iotd_Req . io_Data    = (APTR)DiskTrack;
  1700.                                 DiskRequest -> iotd_Req . io_Length    = NUMSECS * NUMHEADS * TD_SECTOR;
  1701.  
  1702.                                 for(i = 0 ; i < NUMCYLS ; i++)
  1703.                                     if(Error = DiskFormat(i))
  1704.                                         break;
  1705.  
  1706.                                 if(Verify && !Error)
  1707.                                 {
  1708.                                     DiskRequest -> iotd_Req . io_Command = ETD_READ;
  1709.  
  1710.                                     for(i = NUMCYLS - 1 ; i >= 0 && Verify ; i--)
  1711.                                         if(Error = DiskRead(i))
  1712.                                             break;
  1713.                                 }
  1714.                             }
  1715.  
  1716.                             if(!Error)
  1717.                             {
  1718.                                 if(Install || Fast)
  1719.                                 {
  1720.                                     ClearBlock(DiskTrack);
  1721.  
  1722.                                     if(FFS)
  1723.                                         DiskTrack[0] = ID_FFS_DISK;
  1724.                                     else
  1725.                                         DiskTrack[0] = ID_DOS_DISK;
  1726.  
  1727.                                         /* Take the standard boot block? */
  1728.  
  1729.                                     if(Install)
  1730.                                     {
  1731.                                         CopyMemQuick(Standard,DiskTrack,sizeof(Standard));
  1732.  
  1733.                                         if(FFS)
  1734.                                             DiskTrack[0] = ID_FFS_DISK;
  1735.                                         else
  1736.                                             DiskTrack[0] = ID_DOS_DISK;
  1737.  
  1738.                                         DiskTrack[1] = FixBootSum(DiskTrack);
  1739.                                     }
  1740.  
  1741.                                     DiskRequest -> iotd_Req . io_Data = (APTR)DiskTrack;
  1742.  
  1743.                                     if(Error = DiskWrite(0,0))
  1744.                                     {
  1745.                                         i = 0;
  1746.                                         goto WriteError;
  1747.                                     }
  1748.  
  1749.                                     if(Fast)
  1750.                                     {
  1751.                                         DiskRequest -> iotd_Req . io_Data = (APTR)RootTrack;
  1752.  
  1753.                                         if(Error = DiskWrite((NUMTRACKS / 2) * NUMSECS * TD_SECTOR,40))
  1754.                                         {
  1755.                                             i = 40;
  1756.                                             goto WriteError;
  1757.                                         }
  1758.                                     }
  1759.                                 }
  1760.                             }
  1761.                             else
  1762.                             {
  1763. WriteError:                            if(Error > -42)
  1764.                                     SPrintf((char *)InfoText . IText,"Write error Nº%ld, track %ld!",Error,i);
  1765.                                 else
  1766.                                 {
  1767.                                     if(Error == -42)
  1768.                                         Strcpy((char *)InfoText . IText,"*** Format aborted ***");
  1769.                                     else
  1770.                                         SPrintf((char *)InfoText . IText,"Verification error on track %ld!",i);
  1771.                                 }
  1772.  
  1773.                                 GeneralError = TRUE;
  1774.                             }
  1775.  
  1776.                             DiskRequest -> iotd_Req . io_Command = ETD_UPDATE;
  1777.                             DoIO(DiskRequest);
  1778.  
  1779.                             DiskRequest -> iotd_Req . io_Command    = TD_MOTOR;
  1780.                             DiskRequest -> iotd_Req . io_Length    = 0;
  1781.  
  1782.                             DoIO(DiskRequest);
  1783.                         }
  1784.                         else
  1785.                         {
  1786.                             Strcpy(InfoText . IText,"Disk ist write protected!");
  1787.                             GeneralError = TRUE;
  1788.                         }
  1789.                     }
  1790.                     else
  1791.                     {
  1792.                         Strcpy(InfoText . IText,"No disk in drive!");
  1793.                         GeneralError = TRUE;
  1794.                     }
  1795.  
  1796.                     FreeMem(SectorLabel,NUMSECS * NUMHEADS * TD_LABELSIZE);
  1797.                 }
  1798.  
  1799.                 FreeMem(RootTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1800.             }
  1801.  
  1802.             FreeMem(DiskTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1803.         }
  1804.         else
  1805.         {
  1806.             Strcpy(InfoText . IText,"Out of memory!");
  1807.             GeneralError = TRUE;
  1808.         }
  1809.  
  1810.         FreeMem(CheckTrack,NUMSECS * NUMHEADS * TD_SECTOR);
  1811.     }
  1812.     else
  1813.     {
  1814.         Strcpy(InfoText . IText,"Out of memory!");
  1815.         GeneralError = TRUE;
  1816.     }
  1817.  
  1818.     ClearPort();
  1819.  
  1820.     return(GeneralError);
  1821. }
  1822.  
  1823.     /* CentreWindow():
  1824.      *
  1825.      *    Centre a new window under the mouse pointer. I didn't
  1826.      *    want to use the req.library function for this purpose
  1827.      *    and wrote my own special creation.
  1828.      */
  1829.  
  1830. VOID
  1831. CentreWindow(struct NewWindow *New,USHORT OffsetX,USHORT OffsetY)
  1832. {
  1833.     struct Screen PublicScreen;
  1834.  
  1835.         /* Get the screen data. */
  1836.  
  1837.     if(GetScreenData(&PublicScreen,sizeof(struct Screen),New -> Type,New -> Screen))
  1838.     {
  1839.             /* Put it under the mouse pointer. */
  1840.  
  1841.         New -> LeftEdge    = PublicScreen . MouseX - OffsetX;
  1842.         New -> TopEdge    = PublicScreen . MouseY - OffsetY;
  1843.  
  1844.             /* Adjust the x position. */
  1845.  
  1846.         while(New -> LeftEdge + New -> Width > PublicScreen . Width)
  1847.             New -> LeftEdge--;
  1848.  
  1849.         while(New -> LeftEdge < 0)
  1850.             New -> LeftEdge++;
  1851.  
  1852.             /* Adjust the y position. */
  1853.  
  1854.         while(New -> TopEdge + New -> Height > PublicScreen . Height)
  1855.             New -> TopEdge--;
  1856.  
  1857.         while(New -> TopEdge < 0)
  1858.             New -> TopEdge++;
  1859.     }
  1860. }
  1861.  
  1862.     /* DecrementUsage():
  1863.      *
  1864.      *    Decrement the number of currently running Formatters
  1865.      *    and remove the the MsgPort if the current Formatter is
  1866.      *    the last one to terminate.
  1867.      */
  1868.  
  1869. VOID
  1870. DecrementUsage()
  1871. {
  1872.     Forbid();
  1873.  
  1874.     if(!(--GlobalPort -> NumPrgs))
  1875.     {
  1876.         RemPort(&GlobalPort -> Port);
  1877.         FreeMem(GlobalPort,sizeof(struct FormatterPort));
  1878.     }
  1879.  
  1880.     Permit();
  1881. }
  1882.  
  1883.     /* CloseAll():
  1884.      *
  1885.      *    Closes devices and locks the shop.
  1886.      */
  1887.  
  1888. VOID
  1889. CloseAll(BYTE ReturnCode)
  1890. {
  1891.     if(TimeRequest)
  1892.     {
  1893.         if(TimeRequest -> tr_node . io_Device)
  1894.             CloseDevice(TimeRequest);
  1895.  
  1896.         DeleteExtIO(TimeRequest);
  1897.     }
  1898.  
  1899.     if(TimePort)
  1900.         DeletePort(TimePort);
  1901.  
  1902.     if(DiskRequest)
  1903.     {
  1904.         struct TDU_PublicUnit    *PublicUnit;
  1905.         SHORT             i;
  1906.  
  1907.         if(DiskRequest -> iotd_Req . io_Device)
  1908.             CloseDevice(DiskRequest);
  1909.  
  1910.         for(i = 0 ; i < 4 ; i++)
  1911.         {
  1912.             if(OldSteps[i])
  1913.             {
  1914.                 if(!OpenDevice(TD_NAME,i,DiskRequest,0))
  1915.                 {
  1916.                     PublicUnit = (struct TDU_PublicUnit *)DiskRequest -> iotd_Req . io_Unit;
  1917.  
  1918.                     PublicUnit -> tdu_StepDelay = OldSteps[i];
  1919.  
  1920.                     CloseDevice(DiskRequest);
  1921.                 }
  1922.             }
  1923.         }
  1924.  
  1925.         DeleteExtIO(DiskRequest);
  1926.     }
  1927.  
  1928.     if(DiskPort)
  1929.         DeletePort(DiskPort);
  1930.  
  1931.     if(Window)
  1932.     {
  1933.         ClearMenuStrip(Window);
  1934.         CloseWindow(Window);
  1935.     }
  1936.  
  1937.     exit(ReturnCode);
  1938. }
  1939.  
  1940.     /* OpenAll():
  1941.      *
  1942.      *    Opens the devices we need and also the window.
  1943.      */
  1944.  
  1945. VOID
  1946. OpenAll()
  1947. {
  1948.     struct TDU_PublicUnit    *PublicUnit;
  1949.     SHORT             i;
  1950.  
  1951.     if(!(TimePort = CreatePort(NULL,0)))
  1952.         CloseAll(RETURN_FAIL + 0);
  1953.  
  1954.     if(!(TimeRequest = (struct timerequest *)CreateExtIO(TimePort,sizeof(struct timerequest))))
  1955.         CloseAll(RETURN_FAIL + 1);
  1956.  
  1957.     if(OpenDevice(TIMERNAME,UNIT_VBLANK,TimeRequest,0))
  1958.         CloseAll(RETURN_FAIL + 2);
  1959.  
  1960.     if(!(DiskPort = CreatePort(NULL,0)))
  1961.         CloseAll(RETURN_FAIL + 3);
  1962.  
  1963.     if(!(DiskRequest = (struct IOExtTD *)CreateExtIO(DiskPort,sizeof(struct IOExtTD))))
  1964.         CloseAll(RETURN_FAIL + 4);
  1965.  
  1966.     Forbid();
  1967.  
  1968.     for(i = 0 ; i < 4 ; i++)
  1969.     {
  1970.         if(!OpenDevice(TD_NAME,i,DiskRequest,0))
  1971.         {
  1972.             PublicUnit = (struct TDU_PublicUnit *)DiskRequest -> iotd_Req . io_Unit;
  1973.  
  1974.             OldSteps[i] = PublicUnit -> tdu_StepDelay;
  1975.  
  1976.             CloseDevice(DiskRequest);
  1977.         }
  1978.         else
  1979.         {
  1980.             OldSteps[i] = 0;
  1981.  
  1982.             DelayGadgets[i] . Flags |= GADGDISABLED;
  1983.         }
  1984.     }
  1985.  
  1986.     Permit();
  1987.  
  1988.     SetStepDelays(OldSteps);
  1989.  
  1990.     if(OpenDevice(TD_NAME,DriveUnit,DiskRequest,0))
  1991.         CloseAll(RETURN_FAIL + 5);
  1992.  
  1993.     TopEdge = GfxBase -> DefaultFont -> tf_YSize - 8;
  1994.  
  1995.     for(i = 0 ; i < 10 ; i++)
  1996.         FormatGadget[i] . TopEdge += TopEdge;
  1997.  
  1998.     NewWindow . Height += TopEdge;
  1999.  
  2000.     CentreWindow(&NewWindow,FormatGadget[8] . LeftEdge + (FormatGadget[8] . Width >> 1),FormatGadget[8] . TopEdge + (FormatGadget[8] . Height >> 1));
  2001.  
  2002.     if(!(Window = OpenWindow(&NewWindow)))
  2003.         CloseAll(RETURN_FAIL + 6);
  2004. }
  2005.  
  2006.     /* main():
  2007.      *
  2008.      *    That's where all the trouble starts.
  2009.      */
  2010.  
  2011. VOID
  2012. main(int argc,char **argv)
  2013. {
  2014.     static char    *Drive = "DFx:";
  2015.  
  2016.     BYTE         Error,OldUnit,DiskInDrive;
  2017.     ULONG         Time1,Time2,Dummy;
  2018.     SHORT         i;
  2019.  
  2020.         /* Try to find the global MsgPort. */
  2021.  
  2022.     Forbid();
  2023.  
  2024.     if(!(GlobalPort = (struct FormatterPort *)FindPort(PORTNAME)))
  2025.     {
  2026.             /* Didn't find it, create it now. */
  2027.  
  2028.         if(GlobalPort = (struct FormatterPort *)AllocMem(sizeof(struct FormatterPort),MEMF_PUBLIC | MEMF_CLEAR))
  2029.         {
  2030.             GlobalPort -> Port . mp_Node . ln_Name    = PORTNAME;
  2031.             GlobalPort -> Port . mp_Node . ln_Type    = NT_MSGPORT;
  2032.             GlobalPort -> Port . mp_Node . ln_Pri    = 1;
  2033.             GlobalPort -> Port . mp_Flags        = PA_IGNORE;
  2034.  
  2035.             AddPort(&GlobalPort -> Port);
  2036.         }
  2037.     }
  2038.  
  2039.         /* Increment the user count. */
  2040.  
  2041.     if(GlobalPort)
  2042.         GlobalPort -> NumPrgs++;
  2043.  
  2044.     Permit();
  2045.  
  2046.         /* Didn't create the port. */
  2047.  
  2048.     if(!GlobalPort)
  2049.     {
  2050.         if(argc)
  2051.             Printf("Formatter: Unable to create global MsgPort.\a\n");
  2052.  
  2053.         exit(RETURN_FAIL);
  2054.     }
  2055.  
  2056.         /* Do we expect CLI arguments? */
  2057.  
  2058.     if(argc > 1)
  2059.     {
  2060.         char TestString[5];
  2061.  
  2062.             /* Enable debug? */
  2063.  
  2064.         if(argv[ARG_DEBUG])
  2065.             DebugFlag = TRUE;
  2066.  
  2067.             /* Which disk drive? */
  2068.  
  2069.         if(argv[ARG_DRIVE])
  2070.         {
  2071.                 /* Does it match 'DFx:'? */
  2072.  
  2073.             if(Strlen(argv[ARG_DRIVE]) != 4)
  2074.             {
  2075.                 DecrementUsage();
  2076.  
  2077.                 Puts(CLI_Help);
  2078.                 exit(RETURN_WARN);
  2079.             }
  2080.  
  2081.             Strcpy(TestString,argv[ARG_DRIVE]);
  2082.  
  2083.             TestString[2] = 'x';
  2084.  
  2085.             if(Strcmp(Drive,TestString))
  2086.             {
  2087.                 DecrementUsage();
  2088.  
  2089.                 Puts(CLI_Help);
  2090.                 exit(RETURN_WARN);
  2091.             }
  2092.  
  2093.                 /* Can we find the device? */
  2094.  
  2095.             if(!FindDevice(argv[ARG_DRIVE]))
  2096.             {
  2097.                 DecrementUsage();
  2098.  
  2099.                 Printf("Formatter: Unable to find device '%s'.\a\n",argv[ARG_DRIVE]);
  2100.                 exit(RETURN_FAIL);
  2101.             }
  2102.  
  2103.             DriveUnit = argv[ARG_DRIVE][2] - '0';
  2104.         }
  2105.  
  2106.             /* Enable Auto-start? */
  2107.  
  2108.         if(argv[ARG_AUTOSTART])
  2109.         {
  2110.             FormatGadget[4] . Flags |= SELECTED;
  2111.             FormatMenuItem[2] . Flags |= CHECKED;
  2112.         }
  2113.  
  2114.             /* Enable verification? */
  2115.  
  2116.         if(argv[ARG_VERIFY])
  2117.         {
  2118.             FormatGadget[5] . Flags |= SELECTED;
  2119.             FormatMenuItem[4] . Flags |= CHECKED;
  2120.         }
  2121.  
  2122.             /* Enable fast format? */
  2123.  
  2124.         if(argv[ARG_FAST])
  2125.         {
  2126.             FormatGadget[6] . Flags |= SELECTED;
  2127.             FormatMenuItem[3] . Flags |= CHECKED;
  2128.         }
  2129.  
  2130.             /* Enable disk installation? */
  2131.  
  2132.         if(argv[ARG_INSTALL])
  2133.         {
  2134.             FormatGadget[7] . Flags |= SELECTED;
  2135.             FormatMenuItem[5] . Flags |= CHECKED;
  2136.         }
  2137.  
  2138.         if(argv[ARG_FFS])
  2139.             FormatMenuItem[6] . Flags |= CHECKED;
  2140.     }
  2141.  
  2142.     Forbid();
  2143.  
  2144.         /* Is the desired drive already occupied? */
  2145.  
  2146.     if(argc && argv[ARG_DRIVE])
  2147.     {
  2148.         if(GlobalPort -> DriveInUse[DriveUnit])
  2149.         {
  2150.             DecrementUsage();
  2151.  
  2152.             Permit();
  2153.  
  2154.             Printf("Formatter: A different Formatter task is currently using device '%s'.\a\n",argv[ARG_DRIVE]);
  2155.             exit(RETURN_FAIL);
  2156.         }    
  2157.         else
  2158.             GlobalPort -> DriveInUse[DriveUnit] = TRUE;
  2159.     }
  2160.     else
  2161.     {
  2162.             /* Try to find the first disk drive
  2163.              * currently not in use.
  2164.              */
  2165.  
  2166.         DriveUnit = -1;
  2167.  
  2168.         for(i = 0 ; i < 4 ; i++)
  2169.         {
  2170.             if(!GlobalPort -> DriveInUse[i])
  2171.             {
  2172.                 DriveUnit = i;
  2173.                 break;
  2174.             }
  2175.         }
  2176.  
  2177.             /* Didn't find an unused drive. */
  2178.  
  2179.         if(DriveUnit == -1)
  2180.         {
  2181.             DecrementUsage();
  2182.  
  2183.             Permit();
  2184.  
  2185.             DisplayBeep(NULL);
  2186.  
  2187.             exit(RETURN_FAIL);
  2188.         }
  2189.         else
  2190.             GlobalPort -> DriveInUse[DriveUnit] = TRUE;
  2191.     }
  2192.  
  2193.     Permit();
  2194.  
  2195.         /* Take which disk name? */
  2196.  
  2197.     if(argc)
  2198.         Strcpy(FormatText,(argv[ARG_NAME] ? argv[ARG_NAME] : "Blank"));
  2199.     else
  2200.         Strcpy(FormatText,"Blank");
  2201.  
  2202.         /* Set the start gadget text. */
  2203.  
  2204.     FormatIntTxt[8] . IText = (UBYTE *)"Start";
  2205.     FormatMenuIntTxt[14] . IText = FormatInfoText[0];
  2206.  
  2207.         /* Open the resources. */
  2208.  
  2209.     OpenAll();
  2210.  
  2211.         /* The timer request gets initialized. */
  2212.  
  2213.     TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  2214.     TimeRequest -> tr_time . tv_micro    = MILLION / 2;
  2215.  
  2216.         /* Draw the track indicator. */
  2217.  
  2218.     DrawImage(Window -> RPort,&PanelImage,4,11 + TopEdge);
  2219.  
  2220.         /* Mark the device gadgets. */
  2221.  
  2222.     for(i = 0 ; i < 4 ; i++)
  2223.     {
  2224.         Drive[2] = '0' + i;
  2225.  
  2226.         if(!FindDevice(Drive))
  2227.         {
  2228.             FormatGadget[i] . Flags |= GADGDISABLED;
  2229.             FormatMenuItem[8 + i] . Flags &= ~ITEMENABLED;
  2230.         }
  2231.         else
  2232.             FormatGadget[i] . Flags &= ~GADGDISABLED;
  2233.  
  2234.         if(i != DriveUnit)
  2235.             RefreshGadget(Window,&FormatGadget[i],0);
  2236.         else
  2237.         {
  2238.             RefreshGadget(Window,&FormatGadget[i],3);
  2239.             FormatMenuItem[8 + i] . Flags |= CHECKED;
  2240.         }
  2241.     }
  2242.  
  2243.         /* Build the track offset table. */
  2244.  
  2245.     for(i = 0 ; i < NUMCYLS ; i++)
  2246.         OffsetTable[i] = i * (NUMSECS * NUMHEADS * TD_SECTOR);
  2247.  
  2248.         /* Inhibit DFx:. */
  2249.  
  2250.     Drive[2] = '0' + DriveUnit;
  2251.     Inhibit(Drive,TRUE);
  2252.  
  2253.         /* Is there a disk in the drive? */
  2254.  
  2255.     DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
  2256.     DoIO(DiskRequest);
  2257.  
  2258.     DiskInDrive = DiskRequest -> iotd_Req . io_Actual;
  2259.  
  2260.         /* Enable the menu. */
  2261.  
  2262.     SetMenuStrip(Window,&FormatMenu);
  2263.  
  2264.     Window -> Flags &= ~RMBTRAP;
  2265.  
  2266.         /* Go into loop. */
  2267.  
  2268.     FOREVER
  2269.     {
  2270.             /* Wait half a second. */
  2271.  
  2272.         DoIO(TimeRequest);
  2273.  
  2274.             /* Auto-start enabled? */
  2275.  
  2276.         if(AutoStart)
  2277.         {
  2278.                 /* Has a disk been inserted? */
  2279.  
  2280.             DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
  2281.             DoIO(DiskRequest);
  2282.  
  2283.             if(!DiskRequest -> iotd_Req . io_Actual && (DiskRequest -> iotd_Req . io_Actual != DiskInDrive))
  2284.             {
  2285.                 DiskInDrive = DiskRequest -> iotd_Req . io_Actual;
  2286.  
  2287.                 GadgetID = 8;
  2288.  
  2289.                 Class = GADGETUP;
  2290.  
  2291.                 goto CheckClass;
  2292.             }
  2293.  
  2294.             DiskInDrive = DiskRequest -> iotd_Req . io_Actual;
  2295.         }
  2296.  
  2297.             /* News in the mail? */
  2298.  
  2299.         if(Massage = (struct IntuiMessage *)GetMsg(Window -> UserPort))
  2300.         {
  2301.             Class        = Massage -> Class;
  2302.             Code        = Massage -> Code;
  2303.             GadgetID    = ((struct Gadget *)Massage -> IAddress) -> GadgetID;
  2304.  
  2305.             ReplyMsg(Massage);
  2306.  
  2307.                 /* Picked a menu item? */
  2308.  
  2309.             if(Class == MENUPICK)
  2310.                 AdjustClass();
  2311.  
  2312.                 /* Close the window. */
  2313.  
  2314.             if(Class == CLOSEWINDOW)
  2315.             {
  2316.                 Drive[2] = '0' + DriveUnit;
  2317.                 Inhibit(Drive,FALSE);
  2318.  
  2319.                 GlobalPort -> DriveInUse[DriveUnit] = FALSE;
  2320.  
  2321.                 DecrementUsage();
  2322.  
  2323.                 CloseAll(RETURN_OK);
  2324.             }
  2325.  
  2326.             Error = 0;
  2327.  
  2328.                 /* Check the gadgets. */
  2329.  
  2330. CheckClass:        if(Class == GADGETUP)
  2331.             {
  2332.                 switch(GadgetID)
  2333.                 {
  2334.                     case 0:
  2335.                     case 1:
  2336.                     case 2:
  2337.                     case 3:    OldUnit = DriveUnit;
  2338.  
  2339.                         Drive[2] = '0' + GadgetID;
  2340.  
  2341.                         if(!FindDevice(Drive))
  2342.                             break;
  2343.  
  2344.                         if(GadgetID != DriveUnit)
  2345.                         {
  2346.                             Forbid();
  2347.  
  2348.                             if(GlobalPort -> DriveInUse[GadgetID])
  2349.                             {
  2350.                                 Permit();
  2351.  
  2352.                                 DisplayBeep(Window -> WScreen);
  2353.                                 break;
  2354.                             }
  2355.  
  2356.                             GlobalPort -> DriveInUse[GadgetID] = TRUE;
  2357.                             GlobalPort -> DriveInUse[OldUnit]  = FALSE;
  2358.  
  2359.                             Permit();
  2360.  
  2361.                             Drive[2] = '0' + DriveUnit;
  2362.  
  2363.                             Inhibit(Drive,FALSE);
  2364.  
  2365.                             if(!Error)
  2366.                                 CloseDevice(DiskRequest);
  2367.  
  2368.                             DriveUnit = GadgetID;
  2369.  
  2370.                             for(i = 0 ; i < 4 ; i++)
  2371.                             {
  2372.                                 if(i != DriveUnit)
  2373.                                     RefreshGadget(Window,&FormatGadget[i],0);
  2374.                                 else
  2375.                                     RefreshGadget(Window,&FormatGadget[i],3);
  2376.  
  2377.                                 if((FormatMenuItem[8 + i] . Flags & ITEMENABLED) && i == DriveUnit)
  2378.                                     FormatMenuItem[8 + i] . Flags |= CHECKED;
  2379.                                 else
  2380.                                     FormatMenuItem[8 + i] . Flags &= ~CHECKED;
  2381.                             }
  2382.  
  2383.                             Drive[2] = '0' + DriveUnit;
  2384.                             Inhibit(Drive,TRUE);
  2385.  
  2386.                             if(Error = OpenDevice(TD_NAME,DriveUnit,DiskRequest,0))
  2387.                             {
  2388.                                 GadgetID = OldUnit;
  2389.                                 goto CheckClass;
  2390.                             }
  2391.                         }
  2392.  
  2393.                         break;
  2394.  
  2395.                     case 4:    FormatMenuItem[2] . Flags ^= CHECKED;
  2396.                         break;
  2397.  
  2398.                     case 5:    FormatMenuItem[4] . Flags ^= CHECKED;
  2399.                         break;
  2400.  
  2401.                     case 6:    FormatMenuItem[3] . Flags ^= CHECKED;
  2402.                         break;
  2403.  
  2404.                     case 7:    FormatMenuItem[5] . Flags ^= CHECKED;
  2405.                         break;
  2406.  
  2407.                     case 8:    DiskRequest -> iotd_Req . io_Command = TD_CHANGESTATE;
  2408.                         DoIO(DiskRequest);
  2409.  
  2410.                         DiskInDrive = DiskRequest -> iotd_Req . io_Actual;
  2411.  
  2412.                         FormatIntTxt[8] . IText = (UBYTE *)"Stop!";
  2413.                         RefreshGadget(Window,&FormatGadget[8],3);
  2414.  
  2415.                         for(i = 0 ; i < 4 ; i++)
  2416.                             FormatGadget[i] . Flags |= GADGDISABLED;
  2417.  
  2418.                         SetAPen(Window -> RPort,0);
  2419.                         RectFill(Window -> RPort,4,23 + TopEdge,323,34 + TopEdge);
  2420.                         SetAPen(Window -> RPort,1);
  2421.  
  2422.                         FormatGadget[4] . Flags |= GADGDISABLED;
  2423.                         RefreshGadget(Window,&FormatGadget[4],0);
  2424.                         FormatGadget[6] . Flags |= GADGDISABLED;
  2425.                         RefreshGadget(Window,&FormatGadget[6],0);
  2426.                         FormatGadget[9] . Flags |= GADGDISABLED;
  2427.                         RefreshGadget(Window,&FormatGadget[9],0);
  2428.  
  2429.                         FormatMenuItem[ 0] . Flags &= ~ITEMENABLED;
  2430.                         FormatMenuItem[ 2] . Flags &= ~ITEMENABLED;
  2431.                         FormatMenuItem[ 3] . Flags &= ~ITEMENABLED;
  2432.                         FormatMenuItem[ 6] . Flags &= ~ITEMENABLED;
  2433.                         FormatMenuItem[16] . Flags &= ~ITEMENABLED;
  2434.                         FormatMenuItem[13] . Flags &= ~ITEMENABLED;
  2435.  
  2436.                         FormatMenuIntTxt[14] . IText = FormatInfoText[1];
  2437.  
  2438.                         for(i = 0 ; i < 4 ; i++)
  2439.                             FormatMenuItem[8 + i] . Flags &= ~ITEMENABLED;
  2440.  
  2441.                         CurrentTime(&Time1,&Dummy);
  2442.  
  2443.                         Error = Formatter((char *)FormatText);
  2444.  
  2445.                         CurrentTime(&Time2,&Dummy);
  2446.  
  2447.                         if(!Error)
  2448.                         {
  2449.                             Drive[2] = '0' + DriveUnit;
  2450.  
  2451.                             Inhibit(Drive,FALSE);
  2452.                             Delay(3 * TICKS_PER_SECOND);
  2453.                             Inhibit(Drive,TRUE);
  2454.                         }
  2455.  
  2456.                         FormatGadget[4] . Flags &= ~GADGDISABLED;
  2457.                         RefreshGadget(Window,&FormatGadget[4],0);
  2458.                         FormatGadget[6] . Flags &= ~GADGDISABLED;
  2459.                         RefreshGadget(Window,&FormatGadget[6],0);
  2460.                         FormatGadget[9] . Flags &= ~GADGDISABLED;
  2461.                         RefreshGadget(Window,&FormatGadget[9],0);
  2462.  
  2463.                         for(i = 0 ; i < 4 ; i++)
  2464.                         {
  2465.                             Drive[2] = '0' + i;
  2466.  
  2467.                             if(FindDevice(Drive))
  2468.                                 FormatMenuItem[8 + i] . Flags |= ITEMENABLED;
  2469.                         }
  2470.  
  2471.                         FormatMenuItem[ 0] . Flags |= ITEMENABLED;
  2472.                         FormatMenuItem[ 2] . Flags |= ITEMENABLED;
  2473.                         FormatMenuItem[ 3] . Flags |= ITEMENABLED;
  2474.                         FormatMenuItem[ 6] . Flags |= ITEMENABLED;
  2475.                         FormatMenuItem[16] . Flags |= ITEMENABLED;
  2476.                         FormatMenuItem[13] . Flags |= ITEMENABLED;
  2477.  
  2478.                         FormatMenuIntTxt[14] . IText = FormatInfoText[0];
  2479.  
  2480.                         SetAPen(Window -> RPort,0);
  2481.                         RectFill(Window -> RPort,4,23 + TopEdge,323,34 + TopEdge);
  2482.                         SetAPen(Window -> RPort,1);
  2483.  
  2484.                         if(Error)
  2485.                         {
  2486.                             InfoText . LeftEdge = 4 + (320 - 8 * Strlen(InfoText . IText)) / 2;
  2487.                             PrintIText(Window -> RPort,&InfoText,0,TopEdge);
  2488.  
  2489.                             DisplayBeep(Window -> WScreen);
  2490.                         }
  2491.                         else
  2492.                         {
  2493.                             SPrintf((char *)InfoText . IText,"Formatting time %ld:%02ld",abs(Time2 - Time1) / 60,abs(Time2 - Time1) % 60);
  2494.  
  2495.                             InfoText . LeftEdge = 4 + (320 - 8 * Strlen(InfoText . IText)) / 2;
  2496.                             PrintIText(Window -> RPort,&InfoText,0,TopEdge);
  2497.                         }
  2498.  
  2499.                         for(i = 0 ; i < 4 ; i++)
  2500.                         {
  2501.                             Drive[2] = '0' + i;
  2502.  
  2503.                             if(!FindDevice(Drive))
  2504.                                 FormatGadget[i] . Flags |= GADGDISABLED;
  2505.                             else
  2506.                                 FormatGadget[i] . Flags &= ~GADGDISABLED;
  2507.  
  2508.                             if(i != DriveUnit)
  2509.                                 RefreshGadget(Window,&FormatGadget[i],0);
  2510.                             else
  2511.                                 RefreshGadget(Window,&FormatGadget[i],3);
  2512.                         }
  2513.  
  2514.                         FormatIntTxt[8] . IText = (UBYTE *)"Start";
  2515.                         RefreshGadget(Window,&FormatGadget[8],0);
  2516.  
  2517.                         break;
  2518.  
  2519.                     default:break;
  2520.                 }
  2521.             }
  2522.         }
  2523.     }
  2524. }
  2525.