home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_progs / miscutil / disksped.lzh / DiskSpeed / src / DiskSpeed.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-01  |  55.0 KB  |  2,121 lines

  1. /*
  2.  *                          DiskSpeed v4.1
  3.  *                                by
  4.  *                           Michael Sinz
  5.  *
  6.  *             Copyright (c) 1989 by MKSoft Development
  7.  *
  8.  *            MKSoft Development
  9.  *            163 Appledore Drive
  10.  *            Downingtown, PA 19335
  11.  *
  12.  * Yes, this is yet another disk speed testing program, but with a few
  13.  * differences.  It was designed to give the most accurate results of the
  14.  * true disk performance in the system.  For this reason many of
  15.  * DiskSpeed's results may look either lower or higher than current disk
  16.  * performance tests.
  17.  *
  18.  ******************************************************************************
  19.  *                                          *
  20.  *    Reading legal mush can turn your brain into guacamole!              *
  21.  *                                          *
  22.  *        So here is some of that legal mush:                  *
  23.  *                                          *
  24.  * Permission is hereby granted to distribute this program's source          *
  25.  * executable, and documentation for non-commercial purposes, so long as the  *
  26.  * copyright notices are not removed from the sources, executable or          *
  27.  * documentation.  This program may not be distributed for a profit without   *
  28.  * the express written consent of the author Michael Sinz.              *
  29.  *                                          *
  30.  * This program is not in the public domain.                      *
  31.  *                                          *
  32.  * Fred Fish is expressly granted permission to distribute this program's     *
  33.  * source and executable as part of the "Fred Fish freely redistributable     *
  34.  * Amiga software library."                              *
  35.  *                                          *
  36.  * Permission is expressly granted for this program and it's source to be     *
  37.  * distributed as part of the Amicus Amiga software disks, and the          *
  38.  * First Amiga User Group's Hot Mix disks.                      *
  39.  *                                          *
  40.  ******************************************************************************
  41.  *
  42.  * Main code and testing sections...
  43.  */
  44.  
  45. #include    <exec/types.h>
  46. #include    <exec/execbase.h>
  47. #include    <exec/memory.h>
  48. #include    <exec/lists.h>
  49. #include    <exec/nodes.h>
  50. #include    <exec/devices.h>
  51. #include    <exec/io.h>
  52. #include    <exec/ports.h>
  53. #include    <devices/timer.h>
  54. #include    <dos/dos.h>
  55. #include    <dos/dosextens.h>
  56. #include    <intuition/intuition.h>
  57. #include    <intuition/screens.h>
  58. #include    <workbench/workbench.h>
  59. #include    <workbench/startup.h>
  60.  
  61. #include    <clib/exec_protos.h>
  62. #include    <clib/dos_protos.h>
  63. #include    <clib/timer_protos.h>
  64. #include    <clib/intuition_protos.h>
  65. #include    <clib/icon_protos.h>
  66.  
  67. #include    <pragmas/exec_pragmas.h>
  68. #include    <pragmas/dos_pragmas.h>
  69. #include    <pragmas/timer_pragmas.h>
  70. #include    <pragmas/intuition_pragmas.h>
  71. #include    <pragmas/icon_pragmas.h>
  72.  
  73. #include    <string.h>
  74. #include    <stdio.h>
  75.  
  76. #include    "renderinfo.h"
  77. #include    "mks_list.h"
  78. #include    "makeboxes.h"
  79. #include    "diskspeed_rev.h"
  80.  
  81. /*
  82.  * First, the timer stuff...
  83.  */
  84. struct MyTimer
  85. {
  86. struct    timerequest    *tr;
  87. struct    timeval        time;
  88. struct    MsgPort        *port;
  89.     BOOL        Open;
  90. };
  91.  
  92. /*
  93.  * The "TextLine" structure used to display text in the information
  94.  * "window" in DiskSpeed.
  95.  */
  96. struct    TextLine
  97. {
  98. struct    Node    tl_Node;
  99.     ULONG    tl_Size;    /* Size of the allocation */
  100.     char    tl_Text[1];    /* For the NULL... */
  101. };
  102.  
  103. /*
  104.  * My global structure...
  105.  */
  106. struct DiskSpeed
  107. {
  108. struct    Window        *Window;    /* The DiskSpeed window... */
  109. struct    RenderInfo    *ri;        /* MKSoft Render Info */
  110.  
  111.     BPTR    Output;        /* The output file handle! */
  112. struct    Process    *Me;        /* Pointer to my process... */
  113. struct    MyTimer    *timer;        /* Pointer to a timer structure */
  114.  
  115. struct    FileInfoBlock    *fib;    /* Pointer to a FileInfoBlock */
  116.  
  117. /* */
  118. struct    MinList    TextList;    /* The list the results test is linked to... */
  119. struct    DisplayList    *List;    /* The "List" gadget */
  120. /* */
  121.     ULONG    Min_Time;    /* Minimum time in seconds for a test */
  122.     ULONG    Base_CPU;    /* Base CPU available... */
  123.     ULONG    CPU_Total;    /* Sum of CPU availability */
  124.     ULONG    CPU_Count;    /* Count of CPU availability */
  125.  
  126. /* Testing parameters */
  127.     UBYTE    HighDMA;    /* Set to TRUE for high video DMA... */
  128.     UBYTE    Test_DIR;    /* Set to test directory stuff */
  129.     UBYTE    Test_SEEK;    /* Set to test SEEK/READ */
  130.     UBYTE    pad;
  131.  
  132.     ULONG    Align_Types;    /* Set bits of alignment types... */
  133.     ULONG    Mem_TYPES;    /* Set memory type flags to test... */
  134.     ULONG    Test_Size[4];    /* The four test sizes... */
  135.  
  136. /* Now for the gadgets */
  137. struct    Gadget    DeviceGadget;
  138. struct    Gadget    CommentsGadget;
  139. struct    Gadget    StartTestGadget;
  140. struct    Gadget    SaveResultsGadget;
  141. struct    Gadget    StopTestGadget;
  142.  
  143. struct    StringInfo    DeviceInfo;
  144. struct    StringInfo    CommentsInfo;
  145.  
  146. struct    Border    StringBorder[4];
  147. struct    Border    ActionBorder[4];
  148. struct    Border    DetailBorder[2];
  149.  
  150. struct    IntuiText    DeviceText;
  151. struct    IntuiText    CommentsText;
  152. struct    IntuiText    StartTest;
  153. struct    IntuiText    SaveResults;
  154. struct    IntuiText    StopTest;
  155.  
  156.     SHORT    StringVectors[5*2*4];
  157.     SHORT    ActionVectors[5*2*2];
  158.  
  159. /* */
  160.     char    Device[256];    /* Device name under test... */
  161.     char    Comments[256];    /* Comments string gadget... */
  162.     char    Undo[256];    /* Our one UNDO buffer... */
  163.  
  164. /* */
  165.     char    CPU_Type[6];    /* 680?0 in this string (plus NULL) */
  166.     char    Exec_Ver[14];    /* Version of Exec */
  167.  
  168. /* */
  169.     char    tmp1[256];    /* Some temp buffer space... */
  170. };
  171.  
  172. #define    DEVICE_GADGET    1
  173. #define    COMMENT_GADGET    2
  174. #define    TEST_GADGET    3
  175. #define    SAVE_GADGET    4
  176. #define    STOP_GADGET    5
  177.  
  178. extern    struct    Library    *SysBase;
  179. extern    struct    Library    *DOSBase;
  180. extern    struct    Library    *IntuitionBase;
  181. extern    struct    Library    *GfxBase;
  182. extern    struct    Library    *IconBase;
  183.     struct    Library    *LayersBase;
  184.  
  185. /* Some prototypes not given... BTW - This is mainly needed for 1.3 compatibility... ARG!!! */
  186. void *CreateExtIO( struct MsgPort *msg, long size );
  187. struct MsgPort *CreatePort( UBYTE *name, long pri );
  188. void DeleteExtIO( struct IORequest *io );
  189. void DeletePort( struct MsgPort *io );
  190. void DeleteTask( struct Task *task );
  191. void NewList( struct List *list );
  192.  
  193. char    FILE_CREATE[]=    "File Create:   ";
  194. char    FILE_OPEN[]=    "File Open:     ";
  195. char    FILE_SCAN[]=    "Directory Scan:";
  196. char    FILE_DELETE[]=    "File Delete:   ";
  197. char    SEEK_READ[]=    "Seek/Read:     ";
  198.  
  199. char    BYTES_CREATE[]=    "Create file:   ";
  200. char    BYTES_WRITE[]=    "Write to file: ";
  201. char    BYTES_READ[]=    "Read from file:";
  202.  
  203. char    SEEK_UNITS[]=    "seeks/sec";
  204. char    FILE_UNITS[]=    "files/sec";
  205. char    BYTE_UNITS[]=    "bytes/sec";
  206.  
  207. char    FILE_STRING[]=    "%04lx DiskSpeed Test File ";
  208.  
  209. char    TEST_DIR[]=    " DiskSpeed Test Directory ";
  210.  
  211. char    COPYRIGHT[]=    "MKSoft DiskSpeed 4.1  Copyright © 1989-91 MKSoft Development" VERSTAG;
  212.  
  213. char    START_TEST[]=    "Start Test";
  214. char    SAVE_RESULTS[]=    "Save Results";
  215. char    STOP_TEST[]=    "Stop Test";
  216.  
  217. static char fontnam[11]="topaz.font";
  218. struct TextAttr TOPAZ80={fontnam,8,0,FPF_ROMFONT};
  219.  
  220. #define    NUM_FILES    200
  221.  
  222. /*
  223.  * This is the minimum time for test that can be extended/shorted automatically
  224.  * This number should not be set too low otherwise the test results will be
  225.  * inaccurate due to timer granularity.  (in seconds)
  226.  */
  227. #define    MIN_TEST_TIME    8
  228.  
  229. /*
  230.  * This section of code is used to test CPU availability.  Due to the nature of
  231.  * the code, the actual test code for the task is in assembly...
  232.  */
  233. extern    ULONG    __far    CPU_Use_Base;
  234. extern    ULONG    __far    CPU_State_Flag;
  235. extern    ULONG    __far    CPU_Count_Low;
  236. extern    ULONG    __far    CPU_Count_High;
  237.  
  238. struct Task *Init_CPU_Available(void);
  239. void Free_CPU_Available(void);
  240. void CPU_Calibrate(void);
  241.  
  242.  
  243. /* The Wait pointer I use... */
  244. USHORT __chip WaitPointer[36] =
  245. {
  246.     0x0000, 0x0000, 0x0400, 0x07C0, 0x0000, 0x07C0, 0x0100, 0x0380, 0x0000,
  247.     0x07E0, 0x07C0, 0x1FF8, 0x1FF0, 0x3FEC, 0x3FF8, 0x7FDE, 0x3FF8, 0x7FBE,
  248.     0x7FFC, 0xFF7F, 0x7EFC, 0xFFFF, 0x7FFC, 0xFFFF, 0x3FF8, 0x7FFE, 0x3FF8,
  249.     0x7FFE, 0x1FF0, 0x3FFC, 0x07C0, 0x1FF8, 0x0000, 0x07E0, 0x0000, 0x0000
  250. };
  251.  
  252. /*
  253.  * These two defines set up and clear the WaitPointer...
  254.  */
  255. #define    SetWait(x)    SetPointer(x,WaitPointer,16L,16L,-6L,0L)
  256. #define    ClearWait(x)    ClearPointer(x)
  257.  
  258. /*
  259.  * This routine returns the amount of time in the timer...
  260.  * The number returned is in Seconds...
  261.  */
  262. ULONG Read_Timer(struct MyTimer *mt)
  263. {
  264. struct    Library    *TimerBase=(struct Library *)(mt->tr->tr_node.io_Device);
  265.  
  266.     /* Get the current time... */
  267.     mt->tr->tr_node.io_Command=TR_GETSYSTIME;
  268.     mt->tr->tr_node.io_Flags=IOF_QUICK;
  269.     DoIO((struct IORequest *)(mt->tr));
  270.  
  271.     /* Subtract last timer result and store as the timer result */
  272.     SubTime(&(mt->tr->tr_time),&(mt->time));
  273.     return(mt->tr->tr_time.tv_secs);
  274. }
  275.  
  276. /*
  277.  * Start the timer...
  278.  */
  279. void Start_Timer(struct MyTimer *mt)
  280. {
  281.     /* Get the current time... */
  282.     mt->tr->tr_node.io_Command=TR_GETSYSTIME;
  283.     mt->tr->tr_node.io_Flags=IOF_QUICK;
  284.     DoIO((struct IORequest *)(mt->tr));
  285.  
  286.     /* Store current time as the timer result */
  287.     mt->time=mt->tr->tr_time;
  288.  
  289.     /*
  290.      * This here is a nasty trick...  Since the timer device
  291.      * has a low resolution, we wait until we get to the exact
  292.      * cross-over from one TICK to the next.  We know that the
  293.      * tick value is larger than 10 so if the difference
  294.      * between two calls to the timer is > 10 then it must
  295.      * have been a TICK that just went through.  This is
  296.      * not "friendly" code but since we are testing the system
  297.      * and it is not "application" code, it is not a problem.
  298.      */
  299.     while ((mt->tr->tr_time.tv_micro-mt->time.tv_micro) < 10)
  300.     {
  301.         /* Store current time as the timer result */
  302.         mt->time=mt->tr->tr_time;
  303.  
  304.         /* Get the current time... */
  305.         mt->tr->tr_node.io_Command=TR_GETSYSTIME;
  306.         mt->tr->tr_node.io_Flags=IOF_QUICK;
  307.         DoIO((struct IORequest *)(mt->tr));
  308.     }
  309.  
  310.     /* Store current time as the timer result */
  311.     mt->time=mt->tr->tr_time;
  312. }
  313.  
  314. /*
  315.  * Stop the timer...
  316.  */
  317. void Stop_Timer(struct MyTimer *mt)
  318. {
  319. struct    Library    *TimerBase=(struct Library *)(mt->tr->tr_node.io_Device);
  320.  
  321.     /* Get the current time... */
  322.     mt->tr->tr_node.io_Command=TR_GETSYSTIME;
  323.     mt->tr->tr_node.io_Flags=IOF_QUICK;
  324.     DoIO((struct IORequest *)(mt->tr));
  325.  
  326.     /* Subtract last timer result and store as the timer result */
  327.     SubTime(&(mt->tr->tr_time),&(mt->time));
  328.     mt->time=mt->tr->tr_time;
  329. }
  330.  
  331. /*
  332.  * Free a MyTimer structure as best as possible.  Do all of the error checks
  333.  * here since this will also be called for partial timer initializations.
  334.  */
  335. void Free_Timer(struct MyTimer *mt)
  336. {
  337.     if (mt)
  338.     {
  339.         if (mt->port)
  340.         {
  341.             if (mt->tr)
  342.             {
  343.                 if (mt->Open)
  344.                 {
  345.                     CloseDevice((struct IORequest *)(mt->tr));
  346.                 }
  347.                 DeleteExtIO((struct IORequest *)(mt->tr));
  348.             }
  349.             DeletePort(mt->port);
  350.         }
  351.         FreeMem(mt,sizeof(struct MyTimer));
  352.     }
  353. }
  354.  
  355. /*
  356.  * Initialize a MyTimer structure.  It will return NULL if it did not work.
  357.  */
  358. struct MyTimer *Init_Timer(void)
  359. {
  360. struct    MyTimer    *mt;
  361.  
  362.     if (mt=AllocMem(sizeof(struct MyTimer),MEMF_PUBLIC|MEMF_CLEAR))
  363.     {
  364.         mt->Open=FALSE;
  365.         if (mt->port=CreatePort(NULL,0L))
  366.         {
  367.             if (mt->tr=CreateExtIO(mt->port,sizeof(struct timerequest)))
  368.             {
  369.                 if (!OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)(mt->tr),0L))
  370.                 {
  371.                     mt->Open=TRUE;
  372.                 }
  373.             }
  374.         }
  375.         if (!(mt->Open))
  376.         {
  377.             Free_Timer(mt);
  378.             mt=NULL;
  379.         }
  380.     }
  381.     return(mt);
  382. }
  383.  
  384. /*
  385.  * Now, for the routines that will pull in the lines and display them as
  386.  * needed in the display...
  387.  */
  388. void AddDisplayLine(struct DiskSpeed *global,char *line)
  389. {
  390.     ULONG        size=strlen(line);
  391. struct    TextLine    *tline;
  392.  
  393.     if (global->Window)
  394.     {
  395.         if (tline=AllocMem(size+=sizeof(struct TextLine),MEMF_PUBLIC|MEMF_CLEAR))
  396.         {
  397.             tline->tl_Size=size;
  398.             tline->tl_Node.ln_Name=tline->tl_Text;
  399.             strcpy(tline->tl_Text,line);
  400.  
  401.             AddTail((struct List *)&(global->TextList),&(tline->tl_Node));
  402.  
  403.             /* Now display it... */
  404.             FreshList(global->Window,global->List,&(global->TextList));
  405.         }
  406.     }
  407.     else if (global->Output)
  408.     {
  409.         Write(global->Output,line,size);
  410.         Write(global->Output,"\n",1);
  411.     }
  412. }
  413.  
  414. void FreeDisplayList(struct DiskSpeed *global)
  415. {
  416. struct    TextLine    *tline;
  417.  
  418.     while (tline=(struct TextLine *)RemHead((struct List *)&(global->TextList)))
  419.     {
  420.         FreeMem(tline,tline->tl_Size);
  421.     }
  422.  
  423.     /* Update the display */
  424.     if (global->Window) FreshList(global->Window,global->List,NULL);
  425. }
  426.  
  427. /*...*/
  428.  
  429. BOOL Check_Quit(struct DiskSpeed *global)
  430. {
  431. BOOL    worked=TRUE;
  432. struct    IntuiMessage    *msg;
  433.  
  434.     if (global->Window)
  435.     {
  436.         while (msg=(struct IntuiMessage *)GetMsg(global->Window->UserPort))
  437.         {
  438.             if (msg->Class==CLOSEWINDOW) worked=FALSE;
  439.             else if (msg->Class==GADGETUP) if (msg->IAddress=&(global->StopTestGadget)) worked=FALSE;
  440.             Check_ListGadget(global->Window,msg);
  441.             ReplyMsg((struct Message *)msg);
  442.         }
  443.     }
  444.  
  445.     if (SetSignal(0,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) worked=FALSE;
  446.  
  447.     if (!worked) AddDisplayLine(global,"*** Interrupted by user ***");
  448.  
  449.     return(worked);
  450. }
  451.  
  452. /*...*/
  453.  
  454. /*
  455.  * It knows that the Y value is fixed point by n-digits...
  456.  */
  457. ULONG MaxDivide(ULONG x,ULONG y,ULONG digits)
  458. {
  459. ULONG    result;
  460. ULONG    num=0;    /* Number of 10 units adjusted for so far */
  461.  
  462.     while ((x<399999999) && (num<digits))
  463.     {
  464.         x*=10;
  465.         num++;
  466.     }
  467.  
  468.     while (num<digits)
  469.     {
  470.         num++;
  471.         if (num==digits) y+=5;    /* Round it if last digit... */
  472.         y=y/10;
  473.     }
  474.  
  475.     if (y) result=x/y;
  476.     else result=-1;    /* MAX INT if y=0 */
  477.  
  478.     return(result);
  479. }
  480.  
  481. /*
  482.  * Build a string and add it to the display of results.
  483.  * This routine knows how to take the timer results and the CPU
  484.  * results and format them into a string with the given header
  485.  * and the given unit of measure.
  486.  */
  487. VOID Display_Result(struct DiskSpeed *global,char *Header,ULONG number,char *Units)
  488. {
  489. char    *p=global->tmp1;
  490. char    format[48];
  491. ULONG    clicks;    /* To figure out the number of clicks/second */
  492. ULONG    time;
  493. ULONG    tmp_time;
  494.  
  495.     /* First, make sure (as best as possible) that the CPU values are right */
  496.     CPU_State_Flag=TRUE;
  497.     Delay(1);    /* Let it run into the TRUE CPU_State_Flag */
  498.  
  499.     /* 1,000,000 micro = 1 second... */
  500.     time=(global->timer->time.tv_secs * 1000000) + global->timer->time.tv_micro;
  501.     /* time is now in micro seconds... */
  502.  
  503.     number=MaxDivide(number,time,6);
  504.  
  505.     strcpy(format,"%s %9ld %s");
  506.     if (!number)
  507.     {
  508.         strcpy(format,"%s       < %ld %s");
  509.         number=1;
  510.     }
  511.  
  512.     if (global->Base_CPU)
  513.     {
  514.         tmp_time=time;    /* For below... */
  515.  
  516.         while (CPU_Count_High)
  517.         {
  518.             /* Adjust the time and the CPU count as needed */
  519.             tmp_time=tmp_time >> 1;
  520.             CPU_Count_Low=CPU_Count_Low >> 1;
  521.             if (CPU_Count_High & 1) CPU_Count_Low += 0x80000000;
  522.             CPU_Count_High=CPU_Count_High >> 1;
  523.         }
  524.  
  525.         clicks=MaxDivide(CPU_Count_Low,tmp_time,6);
  526.         clicks=(MaxDivide(clicks,global->Base_CPU,3)+5)/10;
  527.         global->CPU_Total+=clicks;
  528.         global->CPU_Count++;
  529.  
  530.         strcat(format,"  |  CPU Available: %ld%%");
  531.     }
  532.  
  533.     sprintf(p,format,Header,number,Units,clicks);
  534.  
  535.     AddDisplayLine(global,p);
  536. }
  537.  
  538. VOID Display_Error(struct DiskSpeed *global,char *test)
  539. {
  540.     sprintf(global->tmp1,"Error:  %s test failed.",test);
  541.     AddDisplayLine(global,global->tmp1);
  542. }
  543.  
  544. /*
  545.  * In order to keep the file create test fair, it must always do
  546.  * the same number of files.  The way filing systems work, many times
  547.  * the get slower as the number of files in a directory grow
  548.  */
  549. BOOL CreateFileTest(struct DiskSpeed *global)
  550. {
  551. BPTR    file;
  552. ULONG    count;
  553. BOOL    worked=TRUE;
  554. char    *p=global->tmp1;    /* For speed reasons */
  555.  
  556.     Start_Timer(global->timer);
  557.     Init_CPU_Available();        /* Start counting free CPU cycles... */
  558.  
  559.     for (count=0;(count<NUM_FILES) && (worked &= Check_Quit(global));count++)
  560.     {
  561.         sprintf(p,FILE_STRING,count);
  562.         if (file=Open(p,MODE_NEWFILE)) Close(file);
  563.         else
  564.         {
  565.             Display_Error(global,"File Create");
  566.             worked=FALSE;
  567.         }
  568.     }
  569.  
  570.     Stop_Timer(global->timer);
  571.  
  572.     if (worked) Display_Result(global,FILE_CREATE,NUM_FILES,FILE_UNITS);
  573.  
  574.     Free_CPU_Available();
  575.  
  576.     return(worked);
  577. }
  578.  
  579. BOOL OpenFileTest(struct DiskSpeed *global)
  580. {
  581. BPTR    file;
  582. ULONG    count=0;
  583. BOOL    worked=TRUE;
  584. char    *p=global->tmp1;
  585.  
  586.     Start_Timer(global->timer);
  587.     Init_CPU_Available();        /* Start counting free CPU cycles... */
  588.     while ((worked &= Check_Quit(global)) && (Read_Timer(global->timer) < global->Min_Time))
  589.     {
  590.         sprintf(p,FILE_STRING,(ULONG)(count % NUM_FILES));
  591.         count++;
  592.         if (file=Open(p,MODE_OLDFILE)) Close(file);
  593.         else
  594.         {
  595.             Display_Error(global,"File Open");
  596.             worked=FALSE;
  597.         }
  598.     }
  599.     Stop_Timer(global->timer);
  600.  
  601.     if (worked) Display_Result(global,FILE_OPEN,count,FILE_UNITS);
  602.  
  603.     Free_CPU_Available();
  604.     return(worked);
  605. }
  606.  
  607. BOOL ScanDirectoryTest(struct DiskSpeed *global)
  608. {
  609. BPTR    lock=NULL;
  610. ULONG    count=0;
  611. BOOL    worked=TRUE;
  612.  
  613.     Start_Timer(global->timer);
  614.     Init_CPU_Available();        /* Start counting free CPU cycles... */
  615.     while ((worked &= Check_Quit(global)) && (Read_Timer(global->timer) < global->Min_Time))
  616.     {
  617.         if (lock)
  618.         {
  619.             if (!ExNext(lock,global->fib)) lock=NULL;
  620.             else count++;
  621.         }
  622.         else
  623.         {
  624.             CurrentDir(lock=CurrentDir(NULL));
  625.             if (Examine(lock,global->fib)) count++;
  626.             else
  627.             {
  628.                 Display_Error(global,"Directory Scan");
  629.                 worked=FALSE;
  630.             }
  631.         }
  632.     }
  633.     Stop_Timer(global->timer);
  634.  
  635.     if (worked) Display_Result(global,FILE_SCAN,count,FILE_UNITS);
  636.  
  637.     Free_CPU_Available();
  638.     return(worked);
  639. }
  640.  
  641. /*
  642.  * In order to keep the file delete test fair, it must always do
  643.  * the same number of files.  The way filing systems work, many times
  644.  * the get slower as the number of files in a directory grow
  645.  */
  646. BOOL DeleteFileTest(struct DiskSpeed *global)
  647. {
  648. ULONG    count;
  649. BOOL    worked=TRUE;
  650. char    *p=global->tmp1;
  651.  
  652.     Start_Timer(global->timer);
  653.     Init_CPU_Available();        /* Start counting free CPU cycles... */
  654.  
  655.     for (count=0;(count<NUM_FILES) && (worked &= Check_Quit(global));count++)
  656.     {
  657.         sprintf(p,FILE_STRING,count);
  658.         if (!DeleteFile(p))
  659.         {
  660.             Display_Error(global,"File Delete");
  661.             worked=FALSE;
  662.         }
  663.     }
  664.  
  665.     Stop_Timer(global->timer);
  666.  
  667.     if (worked) Display_Result(global,FILE_DELETE,NUM_FILES,FILE_UNITS);
  668.  
  669.     Free_CPU_Available();
  670.  
  671.     return(worked);
  672. }
  673.  
  674. BOOL SeekReadTest(struct DiskSpeed *global)
  675. {
  676. BPTR    file;
  677. ULONG    size;
  678. ULONG    count;
  679. LONG    pos=0;
  680. LONG    buffer[16];
  681. BOOL    worked=FALSE;
  682. void    *buf;
  683.  
  684.     /* First we build a file by writing the ROM to disk... */
  685.     if (file=Open(FILE_STRING,MODE_NEWFILE))
  686.     {
  687.         size=0x40000;    /* Start by asking for 256K */
  688.         while (size && (!(buf=AllocMem(size,MEMF_PUBLIC)))) size=size>>1;
  689.  
  690.         if (buf)
  691.         {
  692.             worked=TRUE;
  693.             /* Write a 256K file... */
  694.             count=0x40000/size;
  695.             while ((count>0) && (worked&=Check_Quit(global)))
  696.             {
  697.                 count--;
  698.                 if (size!=Write(file,buf,size))
  699.                 {
  700.                     worked=FALSE;
  701.                     Display_Error(global,"Seek/Read");
  702.                 }
  703.             }
  704.             FreeMem(buf,size);
  705.         }
  706.         else Display_Error(global,"Seek/Read");
  707.  
  708.         Start_Timer(global->timer);
  709.         Init_CPU_Available();        /* Start counting free CPU cycles... */
  710.         while ((worked &= Check_Quit(global)) && (Read_Timer(global->timer) < global->Min_Time))
  711.         {
  712.             Seek(file,pos,OFFSET_BEGINING);
  713.             Read(file,buffer,64);
  714.             count++;
  715.  
  716.             Seek(file,-(pos+64),OFFSET_END);
  717.             Read(file,buffer,64);
  718.             count++;
  719.  
  720.             Seek(file,-(pos+(size/3)),OFFSET_CURRENT);
  721.             Read(file,buffer,64);
  722.             count++;
  723.  
  724.             /* Come up with another position... */
  725.             pos=(pos+(size/11)) % (size/3);
  726.         }
  727.         Stop_Timer(global->timer);
  728.  
  729.         if (worked) Display_Result(global,SEEK_READ,count,SEEK_UNITS);
  730.  
  731.         Free_CPU_Available();
  732.  
  733.         Close(file);
  734.         DeleteFile(FILE_STRING);
  735.     }
  736.     else Display_Error(global,"Seek/Read");
  737.  
  738.     return(worked);
  739. }
  740.  
  741. BOOL SpeedTest(struct DiskSpeed *global,ULONG size,ULONG offset,ULONG mem_type)
  742. {
  743. BOOL    worked=TRUE;
  744. char    *buffer;
  745. char    *mem;        /* What we really allocated */
  746. char    *type;
  747. char    *type2;
  748. ULONG    loop;
  749. ULONG    count;
  750. LONG    times;
  751. BPTR    file=NULL;
  752.  
  753.     AddDisplayLine(global,"");
  754.  
  755.     type="FAST";
  756.     if (mem_type & MEMF_CHIP) type="CHIP";
  757.  
  758.     type2="LONG";
  759.     if (offset & 2) type2="WORD";
  760.     if (offset & 1) type2="BYTE";
  761.  
  762.     if (mem=AllocMem(size+offset,mem_type|MEMF_PUBLIC))
  763.     {
  764.         /* Set up memory... */
  765.         buffer=&(mem[offset]);
  766.  
  767.         for (loop=0;loop<size;loop++) buffer[loop]=(UBYTE)loop;
  768.  
  769.         sprintf(global->tmp1,"Testing with a %ld byte, MEMF_%s, %s-aligned buffer.",size,type,type2);
  770.         AddDisplayLine(global,global->tmp1);
  771.  
  772.         count=0;
  773.         times=0;
  774.  
  775.         Start_Timer(global->timer);
  776.         Init_CPU_Available();        /* Start counting free CPU cycles... */
  777.         while ((worked &= Check_Quit(global)) && (Read_Timer(global->timer) < global->Min_Time))
  778.         {
  779.             if (times<1)
  780.             {
  781.                 if (file) Close(file);
  782.                 DeleteFile(FILE_STRING);
  783.                 if (!(file=Open(FILE_STRING,MODE_NEWFILE)))
  784.                 {
  785.                     Display_Error(global,"Create File");
  786.                     worked=FALSE;
  787.                 }
  788.                 times=0x40000/size;    /* Try to make file at least 256K size */
  789.             }
  790.             if (file)
  791.             {
  792.                 if (size!=Write(file,buffer,size))
  793.                 {
  794.                     Display_Error(global,"Create File");
  795.                     worked=FALSE;
  796.                 }
  797.                 else count+=size;
  798.                 times--;
  799.             }
  800.         }
  801.         Stop_Timer(global->timer);
  802.  
  803.         if (worked) Display_Result(global,BYTES_CREATE,count,BYTE_UNITS);
  804.  
  805.         /* Fill out the file... */
  806.         if (file) while ((worked &= Check_Quit(global)) && (times>0))
  807.         {
  808.             Write(file,buffer,size);
  809.             times--;
  810.         }
  811.  
  812.         if (file) Close(file);
  813.         file=NULL;
  814.  
  815.         if (worked) if (!(file=Open(FILE_STRING,MODE_OLDFILE)))
  816.         {
  817.             Display_Error(global,"Write File");
  818.             worked=FALSE;
  819.         }
  820.  
  821.         count=0;
  822.         times=0;
  823.  
  824.         Start_Timer(global->timer);
  825.         Init_CPU_Available();        /* Start counting free CPU cycles... */
  826.         while ((worked &= Check_Quit(global)) && (Read_Timer(global->timer) < global->Min_Time))
  827.         {
  828.             if (times<1)
  829.             {
  830.                 Seek(file,0,OFFSET_BEGINNING);
  831.                 times=0x40000/size;    /* Try to make file at least 256K size */
  832.             }
  833.             if (size!=Write(file,buffer,size))
  834.             {
  835.                 Display_Error(global,"Write File");
  836.                 worked=FALSE;
  837.             }
  838.             else count+=size;
  839.             times--;
  840.         }
  841.         Stop_Timer(global->timer);
  842.  
  843.         if (worked) Display_Result(global,BYTES_WRITE,count,BYTE_UNITS);
  844.  
  845.         if (file) Close(file);
  846.         file=NULL;
  847.  
  848.         if (worked) if (!(file=Open(FILE_STRING,MODE_OLDFILE)))
  849.         {
  850.             Display_Error(global,"Read File");
  851.             worked=FALSE;
  852.         }
  853.  
  854.         count=0;
  855.         times=0;
  856.  
  857.         Start_Timer(global->timer);
  858.         Init_CPU_Available();        /* Start counting free CPU cycles... */
  859.         while ((worked &= Check_Quit(global)) && (Read_Timer(global->timer) < global->Min_Time))
  860.         {
  861.             if (times<1)
  862.             {
  863.                 Seek(file,0,OFFSET_BEGINNING);
  864.                 times=0x40000/size;    /* Try to make file at least 256K size */
  865.             }
  866.             if (size!=Read(file,buffer,size))
  867.             {
  868.                 Display_Error(global,"Read File");
  869.                 worked=FALSE;
  870.             }
  871.             else count+=size;
  872.             times--;
  873.         }
  874.         Stop_Timer(global->timer);
  875.  
  876.         if (worked)
  877.         {
  878.             for (loop=0;loop<size;loop++) worked &= (buffer[loop]==(UBYTE)loop);
  879.             if (!worked) AddDisplayLine(global,"*** Data Error ***  Buffer did not read correctly.");
  880.         }
  881.  
  882.         if (worked) Display_Result(global,BYTES_READ,count,BYTE_UNITS);
  883.  
  884.         if (file) Close(file);
  885.  
  886.         Free_CPU_Available();
  887.         FreeMem(mem,size+offset);
  888.         DeleteFile(FILE_STRING);
  889.     }
  890.     else
  891.     {
  892.         sprintf(global->tmp1,"Skipping %ld byte MEMF_%s test due to lack of memory.",size,type);
  893.         AddDisplayLine(global,global->tmp1);
  894.     }
  895.  
  896.     return(worked);
  897. }
  898.  
  899. /*
  900.  * Clean up (remove) all of the files in the current directory...
  901.  */
  902. void CleanUpFiles(struct DiskSpeed *global)
  903. {
  904. BPTR    lock;
  905.  
  906.     CurrentDir(lock=CurrentDir(NULL));    /* Get current directory lock */
  907.  
  908.     while (lock)
  909.     {
  910.         if (Examine(lock,global->fib))
  911.         {
  912.             if (ExNext(lock,global->fib)) DeleteFile(global->fib->fib_FileName);
  913.             else lock=NULL;
  914.         }
  915.         else lock=NULL;
  916.     }
  917. }
  918.  
  919. void DoTests(struct DiskSpeed *global)
  920. {
  921. char    *p=global->tmp1;
  922. BOOL    working;
  923. ULONG    memtype;
  924. ULONG    offset;
  925. LONG    buffers;
  926. char    *fstring;
  927. short    size;
  928.  
  929.     /*
  930.      * Ok, so now we are ready to run...  Display the
  931.      * test conditions...
  932.      */
  933.     strcpy(p,"CPU: ");
  934.     strcat(p,global->CPU_Type);
  935.     strcat(p,"  OS Version: ");
  936.     strcat(p,global->Exec_Ver);
  937.     if (global->HighDMA) strcat(p,"  High");
  938.     else strcat(p,"  Normal");
  939.     strcat(p," Video DMA");
  940.     AddDisplayLine(global,p);
  941.  
  942.     /*
  943.      * Now, if we are in 2.0 OS, we can also find out the number of buffers
  944.      * (maybe) on that device.  This is important.
  945.      */
  946.     fstring="Device: %s    Buffers: <information unavailable>";
  947.     if (DOSBase->lib_Version > 36L)
  948.     {
  949.         /*
  950.          * Ok, so we can now try to get a reading of the buffers
  951.          * for the place we are about to test...
  952.          *
  953.          * Note:  Since we are in the "CURRENTDIR" of the test disk,
  954.          * we are using "" as the "device" to which to call AddBuffers()
  955.          */
  956.         if ((buffers=AddBuffers("",0)) > 0) fstring="Device:  %s    Buffers: %ld";
  957.     }
  958.  
  959.     sprintf(p,fstring,global->Device,buffers);
  960.     AddDisplayLine(global,p);
  961.  
  962.     if (global->Comments[0])
  963.     {
  964.         strcpy(p,"Comments: ");
  965.         strcat(p,global->Comments);
  966.         AddDisplayLine(global,p);
  967.     }
  968.  
  969.     AddDisplayLine(global,"");
  970.  
  971.     if (CPU_Use_Base) Delay(60);    /* Make sure filesystem has flushed... */
  972.  
  973.     Init_CPU_Available();
  974.     if (CPU_Use_Base) Delay(75);    /* Get a quick reading (~1.5 seconds) */
  975.     Free_CPU_Available();
  976.  
  977.     if (CPU_Use_Base)
  978.     {
  979.         /*
  980.          * Now, generate a countdown value that is aprox 3 times 1.5 second...
  981.          */
  982.         CPU_Use_Base=(CPU_Count_Low * 3) + 1;
  983.         CPU_Count_Low=CPU_Use_Base;
  984.         Forbid();
  985.         Start_Timer(global->timer);
  986.         CPU_Calibrate();
  987.         Stop_Timer(global->timer);
  988.         Permit();
  989.  
  990.         /*
  991.          * If it looks like we did not get a good reading,
  992.          * set up CPU_Use_Base to 0 in order to turn off
  993.          * CPU readings...
  994.          */
  995.         if (global->timer->time.tv_secs<4)
  996.         {
  997.             AddDisplayLine(global,"CPU Calibration shows that CPU availability tests");
  998.             AddDisplayLine(global,"would be inaccurate in the current system state.");
  999.             CPU_Use_Base=0;
  1000.         }
  1001.         else CPU_Use_Base=MaxDivide(CPU_Use_Base,(global->timer->time.tv_secs * 1000000) + global->timer->time.tv_micro,6);
  1002.     }
  1003.  
  1004.     global->Base_CPU=CPU_Use_Base;
  1005.  
  1006.     if (CPU_Use_Base) sprintf(p,"CPU Speed Rating: %ld",(((CPU_Use_Base/500)+1) >> 1 ));
  1007.     else strcpy(p,"No CPU Speed Rating -- CPU % not available.");
  1008.     AddDisplayLine(global,p);
  1009.     AddDisplayLine(global,"");
  1010.  
  1011.     global->CPU_Total=0L;
  1012.     global->CPU_Count=0L;
  1013.  
  1014.     working=Check_Quit(global);
  1015.  
  1016.     if (working) if (global->Test_DIR)
  1017.     {
  1018.         AddDisplayLine(global,"Testing directory manipulation speed.");
  1019.         if (working) working=CreateFileTest(global);
  1020.         if (working) working=OpenFileTest(global);
  1021.         if (working) working=ScanDirectoryTest(global);
  1022.         if (working) working=DeleteFileTest(global);
  1023.     }
  1024.  
  1025.     if (working) if (global->Test_SEEK)
  1026.     {
  1027.         AddDisplayLine(global,"");
  1028.         if (working) working=SeekReadTest(global);
  1029.     }
  1030.  
  1031.     /* Now for some of the more complex tests */
  1032.     /* result=SpeedTest(global,Buffer,offset,mem_type); */
  1033.  
  1034.     memtype=MEMF_FAST;
  1035.     while (memtype)
  1036.     {
  1037.         if (memtype & global->Mem_TYPES) for (offset=4;offset>0;offset=offset >> 1) if (offset & global->Align_Types)
  1038.         {
  1039.             for (size=0;size<4;size++) if (global->Test_Size[size])
  1040.             {
  1041.                 if (working) working=SpeedTest(global,global->Test_Size[size],offset&3,memtype);
  1042.             }
  1043.         }
  1044.  
  1045.         if (memtype & MEMF_CHIP) memtype=0;
  1046.         else memtype=MEMF_CHIP;
  1047.     }
  1048.  
  1049.     CleanUpFiles(global);
  1050.  
  1051.     if ((working) && (global->CPU_Count))
  1052.     {
  1053.         AddDisplayLine(global,"");
  1054.         global->CPU_Total=(((global->CPU_Total << 1) / global->CPU_Count)+1) >> 1;
  1055.         global->CPU_Count=(((global->Base_CPU * global->CPU_Total) / 50000)+1) >> 1;
  1056.         sprintf(p,"Average CPU Available: %ld%%  |  CPU Availability index: %ld",global->CPU_Total,global->CPU_Count);
  1057.         AddDisplayLine(global,p);
  1058.     }
  1059. }
  1060.  
  1061. void StartTest(struct DiskSpeed *global)
  1062. {
  1063. BPTR    lock;
  1064. BPTR    newlock;
  1065. APTR    oldwindow;
  1066.  
  1067.     oldwindow=global->Me->pr_WindowPtr;
  1068.     global->Me->pr_WindowPtr=(APTR)(-1L);
  1069.  
  1070.     FreeDisplayList(global);
  1071.  
  1072.     AddDisplayLine(global,COPYRIGHT);
  1073.     AddDisplayLine(global,"------------------------------------------------------------");
  1074.  
  1075.     if (lock=Lock(global->Device,ACCESS_READ))
  1076.     {
  1077.         lock=CurrentDir(lock);
  1078.         if (newlock=CreateDir(TEST_DIR))
  1079.         {
  1080.             UnLock(newlock);
  1081.             if (newlock=Lock(TEST_DIR,ACCESS_READ))
  1082.             {
  1083.                 newlock=CurrentDir(newlock);
  1084.  
  1085.                 /*
  1086.                  * Now do all of the tests...
  1087.                  */
  1088.                 DoTests(global);
  1089.  
  1090.                 newlock=CurrentDir(newlock);
  1091.                 UnLock(newlock);
  1092.             }
  1093.             else AddDisplayLine(global,"Error:  Could not access test directory.");
  1094.             DeleteFile(TEST_DIR);
  1095.         }
  1096.         else AddDisplayLine(global,"Error:  Could not create test directory.");
  1097.         lock=CurrentDir(lock);
  1098.         UnLock(lock);
  1099.     }
  1100.     else AddDisplayLine(global,"Error:  Could not get a lock on test device.");
  1101.  
  1102.     global->Me->pr_WindowPtr=oldwindow;
  1103. }
  1104.  
  1105. VOID SetVersionStrings(struct DiskSpeed *global)
  1106. {
  1107. UWORD    flags=((struct ExecBase *)(SysBase))->AttnFlags;
  1108. char    *p;
  1109.  
  1110.     strcpy(global->CPU_Type,"68000");
  1111.     p=&(global->CPU_Type[3]);
  1112.     if (flags & AFF_68010) *p='1';
  1113.     if (flags & AFF_68020) *p='2';
  1114.     if (flags & AFF_68030) *p='3';
  1115.     if (flags & AFF_68040) *p='4';
  1116.  
  1117.     sprintf(global->Exec_Ver,"%ld.%ld",(ULONG)(SysBase->lib_Version),(ULONG)(((struct ExecBase *)SysBase)->SoftVer));
  1118. }
  1119.  
  1120. /*
  1121.  * A simple string check that also works with '=' at the end of the string
  1122.  */
  1123. char *Check_String(char *arg,char *match)
  1124. {
  1125. char    *p;
  1126. char    *next=NULL;
  1127.  
  1128.     p=arg;
  1129.     while (*p)
  1130.     {
  1131.         if (*p=='=')
  1132.         {
  1133.             *p='\0';
  1134.             next=p;
  1135.         }
  1136.         else p++;
  1137.     }
  1138.  
  1139.     if (stricmp(arg,match))
  1140.     {
  1141.         if (next) *next='=';
  1142.         next=NULL;
  1143.     }
  1144.     else
  1145.     {
  1146.         if (next) next++;
  1147.         else next=p;
  1148.     }
  1149.  
  1150.     return(next);
  1151. }
  1152.  
  1153. /*
  1154.  * This routine closes down the GUI
  1155.  */
  1156. void Close_GUI(struct DiskSpeed *global)
  1157. {
  1158.     if (global->Window)
  1159.     {
  1160.         CloseWindow(global->Window);
  1161.         global->Window=NULL;
  1162.     }
  1163.     if (global->List)
  1164.     {
  1165.         FreeListGadget(global->List);
  1166.         global->List=NULL;
  1167.     }
  1168.     if (global->ri)
  1169.     {
  1170.         CleanUp_RenderInfo(global->ri);
  1171.         global->ri=NULL;
  1172.     }
  1173. }
  1174.  
  1175. /*
  1176.  * This routine is used to open the GUI...
  1177.  */
  1178. BOOL Open_GUI(struct DiskSpeed *global)
  1179. {
  1180.     BOOL        worked=FALSE;
  1181.     UWORD        internalwidth;
  1182.     UWORD        internalheight;
  1183. struct    Gadget        *gad=NULL;
  1184. struct    RenderInfo    *ri_temp;
  1185. struct    NewWindow    nw;
  1186.  
  1187.     if (!global->Window)
  1188.     {
  1189.         /* Now, open/set up the GUI... */
  1190.         nw.LeftEdge=0;
  1191.         nw.TopEdge=0;
  1192.         nw.Width=540;
  1193.         nw.Height=169;
  1194.         nw.DetailPen=-1;
  1195.         nw.BlockPen=-1;
  1196.         nw.IDCMPFlags=GADGETDOWN|GADGETUP|CLOSEWINDOW|ACTIVEWINDOW|MOUSEBUTTONS;
  1197.         nw.Flags=SMART_REFRESH|ACTIVATE|NOCAREREFRESH|RMBTRAP|WINDOWCLOSE|WINDOWDEPTH|WINDOWDRAG;
  1198.         nw.FirstGadget=NULL;
  1199.         nw.CheckMark=NULL;
  1200.         nw.Title=COPYRIGHT;
  1201.         nw.Type=WBENCHSCREEN;
  1202.  
  1203.         /*
  1204.          * Take a quick guess at window title bar size
  1205.          */
  1206.         if (ri_temp=Get_RenderInfo(NULL))
  1207.         {
  1208.             nw.Height+=ri_temp->WindowTitle;
  1209.             CleanUp_RenderInfo(ri_temp);
  1210.         }
  1211.  
  1212.         if (global->Window=OpenWindow(&nw)) if ((global->Window->Height-global->Window->BorderTop-global->Window->BorderBottom) > 120)
  1213.         {
  1214.             SetWindowTitles(global->Window,COPYRIGHT,COPYRIGHT);
  1215.             if (global->ri=Get_RenderInfo(global->Window->WScreen))
  1216.             {
  1217.                 internalwidth=global->Window->Width-global->Window->BorderLeft-global->Window->BorderRight;
  1218.                 internalheight=global->Window->Height-global->Window->BorderTop-global->Window->BorderBottom;
  1219.  
  1220.                 global->List=InitListGadget(&TOPAZ80,&gad,1,
  1221.                                 global->ri->Highlight,
  1222.                                 global->ri->Shadow,
  1223.                                 global->Window->BorderLeft+4,
  1224.                                 global->Window->BorderTop+33,
  1225.                                 internalwidth-8,
  1226.                                 internalheight-49);
  1227.  
  1228.                 /*
  1229.                  * Set up borders for the string gadgets
  1230.                  */
  1231.                 global->StringBorder[0].LeftEdge=-5;
  1232.                 global->StringBorder[0].TopEdge=-3;
  1233.                 global->StringBorder[0].FrontPen=global->ri->Highlight;
  1234.                 global->StringBorder[0].DrawMode=JAM1;
  1235.                 global->StringBorder[0].Count=5;
  1236.                 global->StringBorder[0].XY=&(global->StringVectors[0*5*2]);
  1237.                 global->StringBorder[0].NextBorder=&(global->StringBorder[1]);
  1238.  
  1239.                 global->StringBorder[1]=global->StringBorder[0];
  1240.                 global->StringBorder[1].FrontPen=global->ri->Shadow;
  1241.                 global->StringBorder[1].XY=&(global->StringVectors[1*5*2]);
  1242.                 global->StringBorder[1].NextBorder=&(global->StringBorder[2]);
  1243.  
  1244.                 global->StringBorder[2].LeftEdge=-3;
  1245.                 global->StringBorder[2].TopEdge=-2;
  1246.                 global->StringBorder[2].FrontPen=global->ri->Shadow;
  1247.                 global->StringBorder[2].DrawMode=JAM1;
  1248.                 global->StringBorder[2].Count=5;
  1249.                 global->StringBorder[2].XY=&(global->StringVectors[2*5*2]);
  1250.                 global->StringBorder[2].NextBorder=&(global->StringBorder[3]);
  1251.  
  1252.                 global->StringBorder[3]=global->StringBorder[2];
  1253.                 global->StringBorder[3].FrontPen=global->ri->Highlight;
  1254.                 global->StringBorder[3].XY=&(global->StringVectors[3*5*2]);
  1255.                 global->StringBorder[3].NextBorder=NULL;
  1256.  
  1257.                 FillTopLeft_Border(&(global->StringBorder[0]),internalwidth-81,14);
  1258.                 FillBottomRight_Border(&(global->StringBorder[1]),internalwidth-81,14);
  1259.                 FillTopLeft_Border(&(global->StringBorder[2]),internalwidth-85,12);
  1260.                 FillBottomRight_Border(&(global->StringBorder[3]),internalwidth-85,12);
  1261.  
  1262.                 /*
  1263.                  * Now add the few other gadgets to the window...
  1264.                  */
  1265.                 global->DeviceGadget.NextGadget=gad;        gad=&(global->DeviceGadget);
  1266.                 gad->LeftEdge=82+global->Window->BorderLeft;
  1267.                 gad->TopEdge=5+global->Window->BorderTop;
  1268.                 gad->Width=internalwidth-91;
  1269.                 gad->Height=8;
  1270.                 gad->Flags=GADGHCOMP;
  1271.                 gad->Activation=RELVERIFY;
  1272.                 gad->GadgetType=STRGADGET;
  1273.                 gad->GadgetRender=(APTR)&(global->StringBorder[0]);
  1274.                 gad->GadgetText=&(global->DeviceText);
  1275.                 gad->SpecialInfo=(APTR)&(global->DeviceInfo);
  1276.                 gad->GadgetID=DEVICE_GADGET;
  1277.  
  1278.                 global->CommentsGadget=global->DeviceGadget;
  1279.                 global->CommentsGadget.NextGadget=gad;        gad=&(global->CommentsGadget);
  1280.                 gad->TopEdge+=15;
  1281.                 gad->GadgetText=&(global->CommentsText);
  1282.                 gad->SpecialInfo=(APTR)&(global->CommentsInfo);
  1283.                 gad->GadgetID=COMMENT_GADGET;
  1284.  
  1285.                 global->DeviceInfo.Buffer=global->Device;
  1286.                 global->DeviceInfo.UndoBuffer=global->Undo;
  1287.                 global->DeviceInfo.MaxChars=250;
  1288.                 global->CommentsInfo=global->DeviceInfo;
  1289.                 global->CommentsInfo.Buffer=global->Comments;
  1290.  
  1291.                 global->DeviceText.FrontPen=1;
  1292.                 global->DeviceText.BackPen=0;
  1293.                 global->DeviceText.DrawMode=JAM2;
  1294.                 global->DeviceText.LeftEdge=-64;    /* 8 x 8 */
  1295.                 global->DeviceText.TopEdge=0;
  1296.                 global->DeviceText.ITextFont=&TOPAZ80;
  1297.                 global->DeviceText.IText="Device:";
  1298.  
  1299.                 global->CommentsText=global->DeviceText;
  1300.                 global->CommentsText.LeftEdge=-80;    /* 10 x 8 */
  1301.                 global->CommentsText.IText="Comments:";
  1302.  
  1303.                 /*
  1304.                  * Set up borders for the action gadgets (One set for all gadgets...)
  1305.                  */
  1306.                 global->ActionBorder[0].FrontPen=global->ri->Highlight;
  1307.                 global->ActionBorder[0].DrawMode=JAM1;
  1308.                 global->ActionBorder[0].Count=5;
  1309.                 global->ActionBorder[0].XY=&(global->ActionVectors[0*5*2]);
  1310.                 global->ActionBorder[0].NextBorder=&(global->ActionBorder[1]);
  1311.  
  1312.                 global->ActionBorder[1].FrontPen=global->ri->Shadow;
  1313.                 global->ActionBorder[1].DrawMode=JAM1;
  1314.                 global->ActionBorder[1].Count=5;
  1315.                 global->ActionBorder[1].XY=&(global->ActionVectors[1*5*2]);
  1316.                 global->ActionBorder[1].NextBorder=NULL;
  1317.  
  1318.                 global->ActionBorder[2]=global->ActionBorder[0];
  1319.                 global->ActionBorder[2].FrontPen=global->ri->Shadow;
  1320.                 global->ActionBorder[2].NextBorder=&(global->ActionBorder[3]);
  1321.  
  1322.                 global->ActionBorder[3]=global->ActionBorder[1];
  1323.                 global->ActionBorder[3].FrontPen=global->ri->Highlight;
  1324.  
  1325.                 FillTopLeft_Border(&(global->ActionBorder[0]),108,12);
  1326.                 FillBottomRight_Border(&(global->ActionBorder[1]),108,12);
  1327.  
  1328.                 /*
  1329.                  * Now for the two action gadgets at the bottom...
  1330.                  */
  1331.                 global->StartTestGadget.NextGadget=gad;        gad=&(global->StartTestGadget);
  1332.                 gad->LeftEdge=global->Window->BorderLeft+4;
  1333.                 gad->TopEdge=global->Window->Height-global->Window->BorderBottom-14;
  1334.                 gad->Width=108;
  1335.                 gad->Height=12;
  1336.                 gad->Flags=((global->ri->Shadow==global->ri->Highlight) ? GADGHCOMP : GADGHIMAGE);
  1337.                 gad->Activation=RELVERIFY;
  1338.                 gad->GadgetType=BOOLGADGET;
  1339.                 gad->GadgetRender=(APTR)&(global->ActionBorder[0]);
  1340.                 gad->SelectRender=(APTR)&(global->ActionBorder[2]);
  1341.                 gad->GadgetText=&(global->StartTest);
  1342.                 gad->GadgetID=TEST_GADGET;
  1343.  
  1344.                 global->StartTest.FrontPen=1;
  1345.                 global->StartTest.DrawMode=JAM1;
  1346.                 global->StartTest.ITextFont=&TOPAZ80;
  1347.                 global->StartTest.IText=START_TEST;
  1348.                 global->StartTest.TopEdge=2;
  1349.                 global->StartTest.LeftEdge=14;
  1350.  
  1351.                 global->SaveResultsGadget=global->StartTestGadget;
  1352.                 global->SaveResultsGadget.NextGadget=gad;    gad=&(global->SaveResultsGadget);
  1353.                 gad->LeftEdge=global->Window->Width-global->Window->BorderRight-112;
  1354.                 gad->GadgetText=&(global->SaveResults);
  1355.                 gad->GadgetID=SAVE_GADGET;
  1356.  
  1357.                 global->SaveResults=global->StartTest;
  1358.                 global->SaveResults.IText=SAVE_RESULTS;
  1359.                 global->SaveResults.LeftEdge=6;
  1360.  
  1361.                 global->StopTestGadget=global->StartTestGadget;
  1362.                 global->StopTestGadget.NextGadget=gad;    gad=&(global->StopTestGadget);
  1363.                 gad->LeftEdge=(global->Window->Width-108)/2;
  1364.                 gad->GadgetText=&(global->StopTest);
  1365.                 gad->GadgetID=STOP_GADGET;
  1366.  
  1367.                 global->StopTest=global->StartTest;
  1368.                 global->StopTest.IText=STOP_TEST;
  1369.                 global->StopTest.LeftEdge=18;
  1370.  
  1371.                 if (global->List)
  1372.                 {
  1373.                     AddGList(global->Window,gad,-1,-1,NULL);
  1374.                     RefreshGList(gad,global->Window,NULL,-1);
  1375.                     worked=TRUE;
  1376.                 }
  1377.             }
  1378.         }
  1379.  
  1380.         if (!worked) Close_GUI(global);
  1381.     }
  1382.  
  1383.     return(global->Window!=NULL);
  1384. }
  1385.  
  1386. /*
  1387.  * This routine will append to the end of a file the results currently in memory...
  1388.  */
  1389. void Save_Results(struct DiskSpeed *global)
  1390. {
  1391.     BPTR        fh;
  1392. struct    Node        *node;
  1393.  
  1394.     if (fh=Open("DiskSpeed.Results",MODE_OLDFILE))
  1395.     {
  1396.         Seek(fh,0,OFFSET_END);
  1397.         Write(fh,"\n\n\n",2);
  1398.     }
  1399.     else fh=Open("DiskSpeed.Results",MODE_NEWFILE);
  1400.  
  1401.     if (fh)
  1402.     {
  1403.         node=(struct Node *)(global->TextList.mlh_Head);
  1404.         while (node->ln_Succ)
  1405.         {
  1406.             Write(fh,node->ln_Name,strlen(node->ln_Name));
  1407.             Write(fh,"\n",1);
  1408.             node=node->ln_Succ;
  1409.         }
  1410.  
  1411.         Close(fh);
  1412.     }
  1413. }
  1414.  
  1415. /***********************************************************/
  1416. /**                                                       **/
  1417. /**  This is the config requester code for DiskSpeed 4.1  **/
  1418. /**                                                       **/
  1419. /***********************************************************/
  1420.  
  1421. /*
  1422.  * Ok, now for some silly vectors that will be needed to make the 1.3 versions
  1423.  * of some gadgets that are very simple under 2.0
  1424.  */
  1425. SHORT    CheckVec[18]={9,5, 12,8, 18,2, 19,2, 17,2, 11,8, 8,5, 7,5, 10,8};
  1426. SHORT    CheckBox1[10]={24,0, 1,0, 1,9, 0,10, 0,0};
  1427. SHORT    CheckBox2[10]={1,10, 24,10, 24,1, 25,0, 25,10};
  1428.  
  1429. struct    Border    Check_Box2={0,0,0,0,JAM2,5,CheckBox2,NULL};
  1430. struct    Border    Check_Box1={0,0,0,0,JAM2,5,CheckBox1,&Check_Box2};
  1431. struct    Border    CheckOn={0,0,1,0,JAM2,9,CheckVec,&Check_Box1};
  1432. struct    Border    CheckOff={0,0,0,0,JAM2,9,CheckVec,&Check_Box1};
  1433.  
  1434. UBYTE    *BufNames[]={    "Test Buffer 1",
  1435.             "Test Buffer 2",
  1436.             "Test Buffer 3",
  1437.             "Test Buffer 4"    };
  1438.  
  1439. UBYTE    *CheckGads[]={    "DIR",
  1440.             "SEEK",
  1441.             "NOCPU",
  1442.             "LONG",
  1443.             "WORD",
  1444.             "BYTE",
  1445.             "FAST",
  1446.             "CHIP"    };
  1447.  
  1448. SHORT    CheckPos[]={    8,4,
  1449.             8,15,
  1450.             8,26,
  1451.             8,123,
  1452.             8,134,
  1453.             8,145,
  1454.             87,123,
  1455.             87,134    };
  1456.  
  1457. struct    ConfigRequest
  1458. {
  1459. struct    Requester    req;        /* The requester */
  1460.  
  1461. struct    Border        reqBorders[4];    /* Border structures for the requester */
  1462. struct    Border        StringBorder[4];
  1463. struct    Border        BoolBorder[4];
  1464.  
  1465. struct    Gadget        CheckGads[8];    /* The 8 check gadgets */
  1466. struct    Gadget        OkGadget;
  1467. struct    Gadget        MinTimeGadget;
  1468. struct    Gadget        BufGads[4];
  1469.  
  1470. struct    StringInfo    MinTimeString;
  1471. struct    StringInfo    BufString[4];
  1472.  
  1473. struct    IntuiText    reqText[2];    /* Text structures for the requester */
  1474. struct    IntuiText    CheckText[8];    /* Text for the 8 check gadgets */
  1475. struct    IntuiText    OkText;
  1476. struct    IntuiText    MinTimeText;
  1477. struct    IntuiText    BufText[4];
  1478.  
  1479.     SHORT        reqVecs[5*2*4];    /* The vectors for the req border */
  1480.     SHORT        StringVectors[5*2*4];
  1481.     SHORT        BoolVecs[5*2*2];
  1482.  
  1483.     UBYTE        MinTimeBuf[12];
  1484.     UBYTE        Buf[12*4];
  1485.     UBYTE        Undo[12];
  1486. };
  1487.  
  1488. #define    REQ_HEIGHT    165
  1489. #define    REQ_WIDTH    225
  1490.  
  1491. #define    OK_GADGET    99
  1492.  
  1493. /*
  1494.  * This routine will display and handle the config window
  1495.  */
  1496. void Do_Config(struct DiskSpeed *global)
  1497. {
  1498. struct    ConfigRequest    *config;
  1499. struct    Gadget        *gad=NULL;
  1500. struct    IntuiMessage    *msg;
  1501.     short        loop;
  1502.     BOOL        error=TRUE;
  1503.     short        temp;
  1504.  
  1505.     Check_Box1.FrontPen=global->ri->Highlight;
  1506.     Check_Box2.FrontPen=global->ri->Shadow;
  1507.  
  1508.     if (config=AllocMem(sizeof(struct ConfigRequest),MEMF_PUBLIC|MEMF_CLEAR))
  1509.     {
  1510.         InitRequester(&(config->req));
  1511.  
  1512.         config->req.LeftEdge=global->Window->BorderLeft+2;
  1513.         config->req.TopEdge=global->Window->BorderTop+1;
  1514.         config->req.Width=global->Window->Width-global->Window->BorderLeft-global->Window->BorderRight-4;
  1515.         config->req.Height=global->Window->Height-global->Window->BorderTop-global->Window->BorderBottom-2;
  1516.         config->req.ReqBorder=config->reqBorders;
  1517.         config->req.ReqText=config->reqText;
  1518.  
  1519.         /*
  1520.          * Do the OK gadget
  1521.          */
  1522.         config->OkGadget.NextGadget=gad;
  1523.         gad=&(config->OkGadget);
  1524.  
  1525.         gad->LeftEdge=135;
  1526.         gad->TopEdge=148;
  1527.         gad->Width=82;
  1528.         gad->Height=13;
  1529.         gad->Flags=GFLG_GADGHIMAGE;
  1530.         gad->Activation=GACT_RELVERIFY;
  1531.         gad->GadgetType=GTYP_REQGADGET|GTYP_BOOLGADGET;
  1532.         gad->GadgetRender=(APTR)(&(config->BoolBorder[0]));
  1533.         gad->SelectRender=(APTR)(&(config->BoolBorder[2]));
  1534.         gad->GadgetText=&(config->OkText);
  1535.         gad->GadgetID=OK_GADGET;
  1536.  
  1537.         config->OkText.FrontPen=1;
  1538.         config->OkText.DrawMode=JAM2;
  1539.         config->OkText.LeftEdge=33;
  1540.         config->OkText.TopEdge=3;
  1541.         config->OkText.ITextFont=&TOPAZ80;
  1542.         config->OkText.IText="OK";
  1543.  
  1544.         /*
  1545.          * Set up the requester text structures
  1546.          */
  1547.         config->reqText[0]=config->OkText;
  1548.         config->reqText[0].LeftEdge=9;
  1549.         config->reqText[0].TopEdge=42;
  1550.         config->reqText[0].IText="Read/Write Buffer Sizes";
  1551.         config->reqText[0].NextText=&(config->reqText[1]);
  1552.  
  1553.         config->reqText[1]=config->reqText[0];
  1554.         config->reqText[1].TopEdge=111;
  1555.         config->reqText[1].IText="Read/Write Buffer Types";
  1556.         config->reqText[1].NextText=NULL;
  1557.  
  1558.         /*
  1559.          * Now, build the border structures for the requester
  1560.          */
  1561.         config->reqBorders[0].FrontPen=global->ri->Shadow;
  1562.         config->reqBorders[0].DrawMode=JAM2;
  1563.         config->reqBorders[0].Count=5;
  1564.         config->reqBorders[0].XY=&(config->reqVecs[5*2*0]);
  1565.         config->reqBorders[0].NextBorder=&(config->reqBorders[1]);
  1566.  
  1567.         config->reqBorders[1]=config->reqBorders[0];
  1568.         config->reqBorders[1].FrontPen=global->ri->Highlight;
  1569.         config->reqBorders[1].XY=&(config->reqVecs[5*2*1]);
  1570.         config->reqBorders[1].NextBorder=&(config->reqBorders[2]);
  1571.  
  1572.         config->reqBorders[2]=config->reqBorders[1];
  1573.         config->reqBorders[2].TopEdge=1;
  1574.         config->reqBorders[2].LeftEdge=2;
  1575.         config->reqBorders[2].XY=&(config->reqVecs[5*2*2]);
  1576.         config->reqBorders[2].NextBorder=&(config->reqBorders[3]);
  1577.  
  1578.         config->reqBorders[3]=config->reqBorders[0];
  1579.         config->reqBorders[3].TopEdge=1;
  1580.         config->reqBorders[3].LeftEdge=2;
  1581.         config->reqBorders[3].XY=&(config->reqVecs[5*2*3]);
  1582.         config->reqBorders[3].NextBorder=NULL;
  1583.  
  1584.         FillTopLeft_Border(&(config->reqBorders[0]),REQ_WIDTH,REQ_HEIGHT);
  1585.         FillBottomRight_Border(&(config->reqBorders[1]),REQ_WIDTH,REQ_HEIGHT);
  1586.         FillTopLeft_Border(&(config->reqBorders[2]),REQ_WIDTH-4,REQ_HEIGHT-2);
  1587.         FillBottomRight_Border(&(config->reqBorders[3]),REQ_WIDTH-4,REQ_HEIGHT-2);
  1588.  
  1589.         /*
  1590.          * Now, set up the string gadget border structure (it is the same for all)
  1591.          */
  1592.         config->StringBorder[0]=config->reqBorders[1];
  1593.         config->StringBorder[0].LeftEdge=-5;
  1594.         config->StringBorder[0].TopEdge=-3;
  1595.         config->StringBorder[0].XY=&(config->StringVectors[0*5*2]);
  1596.         config->StringBorder[0].NextBorder=&(config->StringBorder[1]);
  1597.  
  1598.         config->StringBorder[1]=config->StringBorder[0];
  1599.         config->StringBorder[1].FrontPen=global->ri->Shadow;
  1600.         config->StringBorder[1].XY=&(config->StringVectors[1*5*2]);
  1601.         config->StringBorder[1].NextBorder=&(config->StringBorder[2]);
  1602.  
  1603.         config->StringBorder[2]=config->StringBorder[1];
  1604.         config->StringBorder[2].LeftEdge=-3;
  1605.         config->StringBorder[2].TopEdge=-2;
  1606.         config->StringBorder[2].XY=&(config->StringVectors[2*5*2]);
  1607.         config->StringBorder[2].NextBorder=&(config->StringBorder[3]);
  1608.  
  1609.         config->StringBorder[3]=config->StringBorder[2];
  1610.         config->StringBorder[3].FrontPen=global->ri->Highlight;
  1611.         config->StringBorder[3].XY=&(config->StringVectors[3*5*2]);
  1612.         config->StringBorder[3].NextBorder=NULL;
  1613.  
  1614.         FillTopLeft_Border(&(config->StringBorder[0]),86,13);
  1615.         FillBottomRight_Border(&(config->StringBorder[1]),86,13);
  1616.         FillTopLeft_Border(&(config->StringBorder[2]),82,11);
  1617.         FillBottomRight_Border(&(config->StringBorder[3]),82,11);
  1618.  
  1619.         /*
  1620.          * Now set up the rel-verify gadget border structure
  1621.          * (Also the same everywhere)
  1622.          */
  1623.         config->BoolBorder[0]=config->StringBorder[0];
  1624.         config->BoolBorder[0].LeftEdge=0;
  1625.         config->BoolBorder[0].TopEdge=0;
  1626.         config->BoolBorder[0].XY=&(config->BoolVecs[0*5*2]);
  1627.         config->BoolBorder[0].NextBorder=&(config->BoolBorder[1]);
  1628.  
  1629.         config->BoolBorder[1]=config->BoolBorder[0];
  1630.         config->BoolBorder[1].FrontPen=global->ri->Shadow;
  1631.         config->BoolBorder[1].XY=&(config->BoolVecs[1*5*2]);
  1632.         config->BoolBorder[1].NextBorder=NULL;
  1633.  
  1634.         config->BoolBorder[2]=config->BoolBorder[0];
  1635.         config->BoolBorder[2].FrontPen=global->ri->Shadow;
  1636.         config->BoolBorder[2].NextBorder=&(config->BoolBorder[3]);
  1637.  
  1638.         config->BoolBorder[3]=config->BoolBorder[1];
  1639.         config->BoolBorder[3].FrontPen=global->ri->Highlight;
  1640.  
  1641.         FillTopLeft_Border(&(config->BoolBorder[0]),82,13);
  1642.         FillBottomRight_Border(&(config->BoolBorder[1]),82,13);
  1643.  
  1644.         /*
  1645.          * Do the MinTime gadget
  1646.          */
  1647.         config->MinTimeGadget.NextGadget=gad;
  1648.         gad=&(config->MinTimeGadget);
  1649.  
  1650.         gad->LeftEdge=128;
  1651.         gad->TopEdge=20;
  1652.         gad->Width=76;
  1653.         gad->Height=8;
  1654.         gad->Flags=GFLG_GADGHCOMP;
  1655.         gad->Activation=GACT_RELVERIFY|GACT_LONGINT;
  1656.         gad->GadgetType=GTYP_STRGADGET;
  1657.         gad->GadgetRender=(APTR)(&(config->StringBorder[0]));
  1658.         gad->GadgetText=&(config->MinTimeText);
  1659.         gad->SpecialInfo=(APTR)(&(config->MinTimeString));
  1660.  
  1661.         config->MinTimeString.Buffer=config->MinTimeBuf;
  1662.         config->MinTimeString.UndoBuffer=config->Undo;
  1663.         config->MinTimeString.MaxChars=11;
  1664.         config->MinTimeString.LongInt=global->Min_Time;
  1665.         sprintf(config->MinTimeBuf,"%ld",config->MinTimeString.LongInt);
  1666.  
  1667.         config->MinTimeText=config->OkText;
  1668.         config->MinTimeText.TopEdge=-12;
  1669.         config->MinTimeText.LeftEdge=12;
  1670.         config->MinTimeText.IText="MINTIME";
  1671.  
  1672.         /*
  1673.          * Now for the 4 buffer gadgets and the Default gadgets for them
  1674.          */
  1675.         for (loop=0;loop<4;loop++)
  1676.         {
  1677.             config->BufGads[loop]=config->MinTimeGadget;
  1678.             config->BufGads[loop].NextGadget=gad;
  1679.             gad=&(config->BufGads[loop]);
  1680.  
  1681.             gad->LeftEdge=136;
  1682.             gad->TopEdge=56+(loop*13);
  1683.             gad->GadgetText=&(config->BufText[loop]);
  1684.             gad->SpecialInfo=(APTR)(&(config->BufString[loop]));
  1685.  
  1686.             config->BufString[loop]=config->MinTimeString;
  1687.             config->BufString[loop].Buffer=&(config->Buf[loop*12]);
  1688.             config->BufString[loop].LongInt=global->Test_Size[loop];
  1689.             sprintf(config->BufString[loop].Buffer,"%ld",config->BufString[loop].LongInt);
  1690.  
  1691.             config->BufText[loop]=config->OkText;
  1692.             config->BufText[loop].TopEdge=0;
  1693.             config->BufText[loop].LeftEdge=-127;
  1694.             config->BufText[loop].IText=BufNames[loop];
  1695.         }
  1696.  
  1697.         /*
  1698.          * Now set up the checkmark gadgets...
  1699.          */
  1700.         for (loop=0;loop<8;loop++)
  1701.         {
  1702.             config->CheckGads[loop].NextGadget=gad;
  1703.             gad=&(config->CheckGads[loop]);
  1704.  
  1705.             gad->LeftEdge=CheckPos[(loop*2)];
  1706.             gad->TopEdge=CheckPos[(loop*2)+1];
  1707.             gad->Width=26;
  1708.             gad->Height=11;
  1709.             gad->Flags=GFLG_GADGHIMAGE;
  1710.             gad->Activation=GACT_TOGGLESELECT;
  1711.             gad->GadgetType=GTYP_REQGADGET|GTYP_BOOLGADGET;
  1712.             gad->GadgetRender=(APTR)(&CheckOff);
  1713.             gad->SelectRender=(APTR)(&CheckOn);
  1714.             gad->GadgetText=&(config->CheckText[loop]);
  1715.  
  1716.             /*
  1717.              * Now, set the initial selected state for this gadget
  1718.              */
  1719.             switch (loop)
  1720.             {
  1721.             case    0:    temp=(global->Test_DIR==TRUE);        break;
  1722.             case    1:    temp=(global->Test_SEEK==TRUE);        break;
  1723.             case    2:    temp=(CPU_Use_Base==FALSE);        break;
  1724.             case    3:    temp=(global->Align_Types & 4);        break;
  1725.             case    4:    temp=(global->Align_Types & 2);        break;
  1726.             case    5:    temp=(global->Align_Types & 1);        break;
  1727.             case    6:    temp=(global->Mem_TYPES & MEMF_FAST);    break;
  1728.             case    7:    temp=(global->Mem_TYPES & MEMF_CHIP);    break;
  1729.             }
  1730.             if (temp) gad->Flags|=GFLG_SELECTED;
  1731.  
  1732.             config->CheckText[loop]=config->OkText;
  1733.             config->CheckText[loop].LeftEdge=30;
  1734.             config->CheckText[loop].TopEdge=2;
  1735.             config->CheckText[loop].IText=CheckGads[loop];
  1736.         }
  1737.  
  1738.         config->req.ReqGadget=gad;
  1739.  
  1740.         if (Request(&(config->req),global->Window))
  1741.         {
  1742.             error=FALSE;
  1743.             temp=TRUE;
  1744.             while(temp)
  1745.             {
  1746.                 WaitPort(global->Window->UserPort);
  1747.                 while (msg=(struct IntuiMessage *)GetMsg(global->Window->UserPort))
  1748.                 {
  1749.                     if (msg->Class==GADGETUP)
  1750.                     {
  1751.                         if (OK_GADGET==((struct Gadget *)(msg->IAddress))->GadgetID) temp=FALSE;
  1752.                     }
  1753.                     ReplyMsg((struct Message *)msg);
  1754.                 }
  1755.             }
  1756.  
  1757.             EndRequest(&(config->req),global->Window);
  1758.  
  1759.             /*
  1760.              * Ok, now get the information back out...
  1761.              */
  1762.             global->Min_Time=config->MinTimeString.LongInt;
  1763.  
  1764.             for (loop=0;loop<4;loop++)
  1765.             {
  1766.                 global->Test_Size[loop]=config->BufString[loop].LongInt;
  1767.             }
  1768.  
  1769.             for (loop=0;loop<8;loop++)
  1770.             {
  1771.                 temp=0;
  1772.                 if (config->CheckGads[loop].Flags & GFLG_SELECTED) temp=1;
  1773.                 switch (loop)
  1774.                 {
  1775.                 case    0:    global->Test_DIR=temp;        break;
  1776.                 case    1:    global->Test_SEEK=temp;        break;
  1777.                 case    2:    CPU_Use_Base=(!temp);        break;
  1778.                 case    3:    global->Align_Types &= (~4);
  1779.                         global->Align_Types |= temp<<2;    break;
  1780.                 case    4:    global->Align_Types &= (~2);
  1781.                         global->Align_Types |= temp<<1;    break;
  1782.                 case    5:    global->Align_Types &= (~1);
  1783.                         global->Align_Types |= temp;    break;
  1784.                 case    6:    global->Mem_TYPES &= (~MEMF_FAST);
  1785.                         global->Mem_TYPES |= (temp * MEMF_FAST);
  1786.                         break;
  1787.                 case    7:    global->Mem_TYPES &= (~MEMF_CHIP);
  1788.                         global->Mem_TYPES |= (temp * MEMF_CHIP);
  1789.                         break;
  1790.                 }
  1791.             }
  1792.         }
  1793.  
  1794.         FreeMem(config,sizeof(struct ConfigRequest));
  1795.     }
  1796.  
  1797.     if (error) AddDisplayLine(global,"Could not open configuration requester.");
  1798. }
  1799.  
  1800. /**********************************************************/
  1801. /**                                                      **/
  1802. /**  End of the config requester code for DiskSpeed 4.1  **/
  1803. /**                                                      **/
  1804. /**********************************************************/
  1805.  
  1806. /*
  1807.  * This routine is used to control the GUI
  1808.  */
  1809. void Do_GUI(struct DiskSpeed *global)
  1810. {
  1811.     BOOL        done=FALSE;
  1812. struct    IntuiMessage    *msg;
  1813.  
  1814.     while (!done)
  1815.     {
  1816.         WaitPort(global->Window->UserPort);
  1817.         while (msg=(struct IntuiMessage *)GetMsg(global->Window->UserPort))
  1818.         {
  1819.             if (!Check_ListGadget(global->Window,msg))
  1820.             {
  1821.                 if (msg->Class==CLOSEWINDOW) done=TRUE;
  1822.                 else if ((msg->Class==MOUSEBUTTONS) && (msg->Code==MENUDOWN)) Do_Config(global);
  1823.                 else if (msg->Class==GADGETUP)
  1824.                 {
  1825.                     switch(((struct Gadget *)(msg->IAddress))->GadgetID)
  1826.                     {
  1827.                     case DEVICE_GADGET:    ActivateGadget(&(global->CommentsGadget),global->Window,NULL);
  1828.                                 break;
  1829.                     case COMMENT_GADGET:    ActivateGadget(&(global->DeviceGadget),global->Window,NULL);
  1830.                                 break;
  1831.                     case TEST_GADGET:    SetWait(global->Window);
  1832.                                 StartTest(global);
  1833.                                 ClearWait(global->Window);
  1834.                                 break;
  1835.                     case SAVE_GADGET:    SetWait(global->Window);
  1836.                                 Save_Results(global);
  1837.                                 ClearWait(global->Window);
  1838.                                 break;
  1839.                     }
  1840.                 }
  1841.                 else if (msg->Class==ACTIVEWINDOW)
  1842.                 {
  1843.                     ActivateGadget(&(global->DeviceGadget),global->Window,NULL);
  1844.                 }
  1845.             }
  1846.             ReplyMsg((struct Message *)msg);
  1847.         }
  1848.     }
  1849.     /* Shut down GUI */
  1850.     Close_GUI(global);
  1851. }
  1852.  
  1853. /*
  1854.  * DRIVE/K    - select drive  (Default is current directory)
  1855.  * COMMENT/K    - set comment string
  1856.  * ALL/S    - select all tests
  1857.  * DIR/S    - setect DIR tests
  1858.  * SEEK/S    - select SEEK tests
  1859.  * CHIP/S    - select CHIP memory buffer tests
  1860.  * FAST/S    - select FAST memory buffer tests
  1861.  * LONG/S    - select LONG aligned tests
  1862.  * WORD/S    - select WORD aligned tests
  1863.  * BYTE/S    - select BYTE aligned tests
  1864.  * NOCPU/S    - turn off CPU availability tests
  1865.  * BUF1/K/N    - select buffer size 1
  1866.  * BUF2/K/N    - select buffer size 2
  1867.  * BUF3/K/N    - select buffer size 3
  1868.  * BUF4/K/N    - select buffer size 4
  1869.  * MINTIME/K/N    - select the minimum test time (default=8) in seconds
  1870.  * WINDOW/S    - use the GUI even though started from the CLI
  1871.  */
  1872.  
  1873. /*
  1874.  * do the command line parsing here...
  1875.  */
  1876. BOOL ParseArg(struct DiskSpeed *global,int argc,char *argv[],int start)
  1877. {
  1878. int    loop;
  1879. char    *arg;
  1880. char    *next;
  1881. BOOL    working=TRUE;
  1882. BOOL    window=FALSE;
  1883.  
  1884.     for (loop=start;loop<argc;loop++)
  1885.     {
  1886.         arg=argv[loop];
  1887.         if (*arg=='?')
  1888.         {
  1889.             loop=argc;
  1890.             working=FALSE;
  1891.         }
  1892.         else if (next=Check_String(arg,"DRIVE"))
  1893.         {
  1894.             if (!(*next))
  1895.             {
  1896.                 loop++;
  1897.                 if (loop<argc) next=argv[loop];
  1898.             }
  1899.             if (strlen(next)>255) *next='\0';
  1900.             if (*next) strcpy(global->Device,next);
  1901.             else working=FALSE;
  1902.         }
  1903.         else if (next=Check_String(arg,"COMMENT"))
  1904.         {
  1905.             if (!(*next))
  1906.             {
  1907.                 loop++;
  1908.                 if (loop<argc) next=argv[loop];
  1909.             }
  1910.             if (strlen(next)>255) *next='\0';
  1911.             if (*next) strcpy(global->Comments,next);
  1912.             else working=FALSE;
  1913.         }
  1914.         else if (Check_String(arg,"ALL"))
  1915.         {
  1916.             /* All tests */
  1917.             global->Test_DIR=TRUE;
  1918.             global->Test_SEEK=TRUE;
  1919.             global->Align_Types=4|2|1;
  1920.             global->Mem_TYPES=MEMF_CHIP | MEMF_FAST;
  1921.         }
  1922.         else if (next=Check_String(arg,"BUF1"))
  1923.         {
  1924.             if (!(*next))
  1925.             {
  1926.                 loop++;
  1927.                 if (loop<argc) next=argv[loop];
  1928.             }
  1929.             if (*next) stcd_l(next,&(global->Test_Size[0]));
  1930.             else working=FALSE;
  1931.         }
  1932.         else if (next=Check_String(arg,"BUF2"))
  1933.         {
  1934.             if (!(*next))
  1935.             {
  1936.                 loop++;
  1937.                 if (loop<argc) next=argv[loop];
  1938.             }
  1939.             if (*next) stcd_l(next,&(global->Test_Size[1]));
  1940.             else working=FALSE;
  1941.         }
  1942.         else if (next=Check_String(arg,"BUF3"))
  1943.         {
  1944.             if (!(*next))
  1945.             {
  1946.                 loop++;
  1947.                 if (loop<argc) next=argv[loop];
  1948.             }
  1949.             if (*next) stcd_l(next,&(global->Test_Size[2]));
  1950.             else working=FALSE;
  1951.         }
  1952.         else if (next=Check_String(arg,"BUF4"))
  1953.         {
  1954.             if (!(*next))
  1955.             {
  1956.                 loop++;
  1957.                 if (loop<argc) next=argv[loop];
  1958.             }
  1959.             if (*next) stcd_l(next,&(global->Test_Size[3]));
  1960.             else working=FALSE;
  1961.         }
  1962.         else if (next=Check_String(arg,"MINTIME"))
  1963.         {
  1964.             if (!(*next))
  1965.             {
  1966.                 loop++;
  1967.                 if (loop<argc) next=argv[loop];
  1968.             }
  1969.             if (*next) stcd_l(next,&(global->Min_Time));
  1970.             else working=FALSE;
  1971.         }
  1972.         else if (Check_String(arg,"DIR")) global->Test_DIR=TRUE;
  1973.         else if (Check_String(arg,"SEEK")) global->Test_SEEK=TRUE;
  1974.         else if (Check_String(arg,"CHIP")) global->Mem_TYPES|=MEMF_CHIP;
  1975.         else if (Check_String(arg,"FAST")) global->Mem_TYPES|=MEMF_FAST;
  1976.         else if (Check_String(arg,"LONG")) global->Align_Types|=4;
  1977.         else if (Check_String(arg,"WORD")) global->Align_Types|=2;
  1978.         else if (Check_String(arg,"BYTE")) global->Align_Types|=1;
  1979.         else if (Check_String(arg,"NOCPU")) CPU_Use_Base=FALSE;
  1980.         else if (Check_String(arg,"WINDOW")) window=TRUE;
  1981.         else
  1982.         {    /* Did not match, so error */
  1983.             working=FALSE;
  1984.         }
  1985.     }
  1986.  
  1987.     if (global->Min_Time < 1) global->Min_Time=1;
  1988.  
  1989.     if (working) if (window) working=Open_GUI(global);
  1990.  
  1991.     return(working);
  1992. }
  1993.  
  1994. /*
  1995.  * This routine is called when we want to run from a GUI
  1996.  * Normally, it is only called when started from Workbench
  1997.  * or when the CLI WINDOW option is given...
  1998.  */
  1999. void DoWorkbench(struct DiskSpeed *global,int argc,char *argv[])
  2000. {
  2001. struct    WBStartup    *wbmsg;
  2002. struct    WBArg        *wbarg;
  2003.     BPTR        lock;
  2004. struct    DiskObject    *icon;
  2005.  
  2006.     wbmsg=(struct WBStartup *)argv;
  2007.  
  2008.     if ((wbarg=wbmsg->sm_ArgList) && (wbmsg->sm_NumArgs))
  2009.     {
  2010.         /*
  2011.          * Check if we were started as a project and
  2012.          * use that icon insted...
  2013.          */
  2014.         if ((wbmsg->sm_NumArgs) > 1) wbarg++;
  2015.  
  2016.         lock=CurrentDir(wbarg->wa_Lock);
  2017.  
  2018.         argc=0;
  2019.         if (icon=GetDiskObject(wbarg->wa_Name))
  2020.         {
  2021.             argv=icon->do_ToolTypes;
  2022.             while (argv[argc]) argc++;
  2023.             /*
  2024.              * Don't care about argument errors in tooltypes
  2025.              * since other things may have been in there...
  2026.              */
  2027.             ParseArg(global,argc,argv,0);
  2028.             FreeDiskObject(icon);
  2029.         }
  2030.  
  2031.         if (!argc)
  2032.         {
  2033.             /* All tests */
  2034.             global->Test_DIR=TRUE;
  2035.             global->Test_SEEK=TRUE;
  2036.             global->Align_Types=4|2|1;
  2037.             global->Mem_TYPES=MEMF_CHIP | MEMF_FAST;
  2038.         }
  2039.  
  2040.         if (Open_GUI(global)) Do_GUI(global);
  2041.  
  2042.         CurrentDir(lock);
  2043.     }
  2044. }
  2045.  
  2046. /*
  2047.  * This is the CLI starting point.  We do the command line parsing here...
  2048.  */
  2049. void DoCLI(struct DiskSpeed *global,int argc,char *argv[])
  2050. {
  2051.     if (ParseArg(global,argc,argv,1))
  2052.     {
  2053.         if (global->Window) Do_GUI(global);
  2054.         else StartTest(global);
  2055.     }
  2056.     else AddDisplayLine(global,"DRIVE/K,ALL/S,DIR/S,SEEK/S,CHIP/S,FAST/S,LONG/S,WORD/S,BYTE/S,NOCPU/S,BUF1/K/N,BUF2/K/N,BUF3/K/N,BUF4/K/N,MINTIME/K/N,WINDOW/S");
  2057. }
  2058.  
  2059. void main(int argc, char *argv[])
  2060. {
  2061. struct    DiskSpeed    *global;
  2062.  
  2063.     CPU_Use_Base=TRUE;    /* We want to test with CPU */
  2064.  
  2065.     if (IntuitionBase=OpenLibrary("intuition.library",33L))
  2066.     {
  2067.         if (GfxBase=OpenLibrary("graphics.library",33L))
  2068.         {
  2069.             if (LayersBase=OpenLibrary("layers.library",33L))
  2070.             {
  2071.                 if (IconBase=OpenLibrary("icon.library",33L))
  2072.                 {
  2073.                     if (global=AllocMem(sizeof(struct DiskSpeed),MEMF_PUBLIC|MEMF_CLEAR))
  2074.                     {
  2075.                         NewList((struct List *)&(global->TextList));
  2076.                         SetVersionStrings(global);
  2077.                         global->Me=(struct Process *)FindTask(NULL);
  2078.  
  2079.                         /* Standard MinTime */
  2080.                         global->Min_Time=MIN_TEST_TIME;
  2081.  
  2082.                         /* Standard sizes */
  2083.                         global->Test_Size[0]=0x200;
  2084.                         global->Test_Size[1]=0x1000;
  2085.                         global->Test_Size[2]=0x8000;
  2086.                         global->Test_Size[3]=0x40000;
  2087.  
  2088.                         if (global->fib=AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC))
  2089.                         {
  2090.                             if (global->timer=Init_Timer())
  2091.                             {
  2092.                                 /*
  2093.                                  * Now either set up Window or Output
  2094.                                  * depending on where we were started...
  2095.                                  *
  2096.                                  * If we can not get Output, we set up the window...
  2097.                                  */
  2098.                                 if ((argc) && (global->Output=Output()))
  2099.                                 {
  2100.                                     DoCLI(global,argc,argv);
  2101.                                 }
  2102.                                 else DoWorkbench(global,argc,argv);
  2103.  
  2104.                                 Free_Timer(global->timer);
  2105.                             }
  2106.                             FreeMem(global->fib,sizeof(struct FileInfoBlock));
  2107.                         }
  2108.  
  2109.                         FreeDisplayList(global);
  2110.                         FreeMem(global,sizeof(struct DiskSpeed));
  2111.                     }
  2112.                     CloseLibrary(IconBase);
  2113.                 }
  2114.                 CloseLibrary(LayersBase);
  2115.             }
  2116.             CloseLibrary(GfxBase);
  2117.         }
  2118.         CloseLibrary(IntuitionBase);
  2119.     }
  2120. }
  2121.