PROGRAM SearchTester
?
? Program written by Neal Countryman to visually compare the performance
? of the Brute Force Search, Binary Search, and Modified Binary Search
? algorithms on an ordered list of 1793 elements. 1000 trials of the
? respective techniques are used on a randomly generated target, and the
? number of integer compares with array elements (and thus the effective
? speed of the algorithms) are tabulated and displayed by the program in
? a unique way. Requires the presence of the file DS1.Screen on the F-Basic
? Sample Programs Disk.
?
? NOTE: This program is not for the squeemish as direct manipulation of
? operating system memory and data structures is used to effect the visual
? displays.
?
? Upon execution, the program can be "started" by moving the mouse to the
? on/off switch in the upper right corner of the display and clicking on
? it. To start any of the three timing tests, the mouse should be moved
? to the respective start box at the bottom of the screen and clicked on
? the appropiate choice. To end the program, reposition the mouse to the
? on/off switch in the upper right and click on it.
?
? The visual rendering of the Binary Search and Modified Binary Search are
? not as dynamic as that of the Brute Force Search algorithm, but
? illustrates how much better these algorithms are in terms of number of
? compares.
? 
?
CONSTANT ON=1, OFF=0, POWER=0, BFLED=1, BLED=2, MBLED=3, FullDelay=0
CONSTANT NoDelay=0, All = 4

SUBPROGRAM
   SUBROUTINE BruteForce, Binary, ModBinary, Startup, DDisplay, CMOVE, CWAIT
   SUBROUTINE LED, ADisplay, ShutDown, Toggle

GLOBAL
   INTEGER  BP4, BP5, SCR, WND, DOSBase, GraBase, SSDispLoc(3), UCopList
   INTEGER  IntBase, ViewPort, Search(1793), OldNum(3), CUMeter(3)
   INTEGER  OldBGBits(3), OldBGLights(3), OldBGVal(3), OldBGOffset(3)
   INTEGER  Color1(3), Color2(3), Color7(3)
   WORD     Switch(75), Digits(1056), Arc(82)

LOCAL
   INTEGER  X, MouseX, MouseY



?First bitplane of switch
   DATA(Switch,1088,2080*3,0,0,1088*2,1728,7920,6832,13208*2)
   DATA(12568,6192,8176,1984,0*8)
?Second bitplane of switch
   DATA(0*4,2080*3,0*3,1088,3168*2,3808,1984,0*10)
?Fifth bitplane of switch
   DATA(1984,4064*6,8176,32764*2,65534*5,32764*2,8176,1984,0*6)


?Define 0
   DATA(Digits,1022,508,1025,1539*7,1025,0,0,1025,1539*7,1025,508,1022,0*8)
?Define 1
   DATA(0,0,1,3*7,1,0,0,1,3*7,1,0*10)
?Define 2
   DATA(1022,508,1,3*7,1,508*2,1024,1536*7,1024,508,1022,0*8)
?Define 3
   DATA(1022,508,1,3*7,1,508*2,1,3*7,1,508,1022,0*8)
?Define 4
   DATA(0,0,1025,1539*7,1025,508*2,1,3*7,1,0*10)
?Define 5
   DATA(1022,508,1024,1536*7,1024,508*2,1,3*7,1,508,1022,0*8)
?Define 6
   DATA(1022,508,1024,1536*7,1024,508*2,1025,1539*7,1025,508,1022,0*8)
?Define 7
   DATA(1022,508,1,3*7,1,0,0,1,3*7,1,0*10)
?Define 8
   DATA(1022,508,1025,1539*7,1025,508*2,1025,1539*7,1025,508,1022,0*8)
?Define 9
   DATA(1022,508,1025,1539*7,1025,508*2,1,3*7,1,508,1022,0*8)
?Define blank
   DATA(0*32)


?** Offsets for 7-segment meters. **
   DATA(SSDispLoc,5682,5696,5710)


?** Y points along the meter arc. **
   DATA(Arc,65,65,64,63,62,61,61,60,60,59)
   DATA(58,58,57,57,56,56,55,55,55,54)
   DATA(54,53,53,53,53,52,52,52,52,51)
   DATA(51,51,51,51,51,51,51,51,51,51)
   DATA(50,51,51,51,51,51,51,51,51,51)
   DATA(51,51,52,52,52,52,53,53,53,53)
   DATA(54,54,55,55,55,56,56,57,57,58)
   DATA(58,59,60,60,61,61,62,63,64,65,65)


?** All the meters start out at 0. **
   DATA(OldNum,0*3)


?** X values for the CU-meter adjustment screws. **
   DATA(CUMeter,50,160,270)


?** Bar graph data. **
   DATA(OldBGBits,1,7,5)
   DATA(OldBGLights,0,0,0)
   DATA(OldBGVal,FFFFFF80'16,FFFFFFFE'16,FFFFFFF8'16)
   DATA(OldBGOffset,4960,4973,4987)






?** Seed random number generator. **
   RANDOMIZE(123456)


?** Finish up the table for 7-seg displays. **
   FOR X = 1 TO 352
      Digits(X+352) = Digits(X) LSL 2
      Digits(X+704) = Digits(X) LSL 5
   NEXT X


?** Create the Search array. **
   FOR X = 1 TO 1793
      Search(X) = X
   NEXT X


?** Go load the main screen and display it. **
   Startup()


?** Watch the mouse activity. **
   REPEAT
      WHILE BTST(6,^BFE001'16)
      ENDWHILE

      MouseX = $(SCR + 18)
      MouseY = $(SCR + 16)

      IF (MouseY-178>=0) AND (MouseY-198<=0) THEN
         IF (MouseX-32>=0) AND (MouseX-67<=0) THEN
            LED(BFLED,ON)
               BruteForce()
            LED(BFLED,OFF)

         ELSE IF (MouseX-142>=0) AND (MouseX-177<=0) THEN
            LED(BLED,ON)
               Binary()
            LED(BLED,OFF)

         ELSE IF (MouseX-252>=0) AND (MouseX-287<=0) THEN
            LED(MBLED,ON)
               ModBinary()
            LED(MBLED,OFF)

         ENDIF
      ENDIF
   UNTIL (MouseX-272>=0) AND (MouseX-286<=0) AND (MouseY-5>=0) AND (MouseY-23<=0)


?** Turn the amp off and leave. **
   ShutDown()


END






SUBROUTINE BruteForce
?************************************************************************
?**  BruteForce  **                                        NC: 01/24/88 *
?************************************************************************
?*                                                                      *
?*    This routine performs a brute force search for a random number    *
?* between 1 and 1793 while counting the number of array comparisons    *
?* done in the process.                                                 *
?*                                                                      *
?************************************************************************

   LOCAL
      INTEGER Count, Index, Target, Compares, TCompares


   TCompares = 0
   DDisplay(1,0)
   ADisplay(1,0)

   FOR Count = 1 TO 1000
      Index = 0
      Compares = 0
      Target = (RANDOM()\1793) + 1

      REPEAT
         INC(Index)
         INC(Compares)
      UNTIL Search(Index)=Target

      TCompares = TCompares + Compares
      DDisplay(1,TCompares/Count)
      ADisplay(1,TCompares/Count)
   NEXT Count

   GRETURN
END




SUBROUTINE Binary
?************************************************************************
?**  Binary  **                                            NC: 01/24/88 *
?************************************************************************
?*                                                                      *
?*    This routine performs a binary search for a randomly generated #  *
?* between 1 and 1793 while at the same time counting the # of compares *
?* it does to actual array elements.                                    *
?*                                                                      *
?************************************************************************
   LOCAL
      INTEGER  First, Last, Middle, Length, Compares, TCompares
      INTEGER  Count, Target


   TCompares = 0
   DDisplay(2,0)
   ADisplay(2,0)

   FOR Count = 1 TO 1000
      First = 1
      Last = 1793
      Length = 1793
      Compares = 0
      Target = (RANDOM()\1793) + 1

      {STEP2}
         IF (Length <= 2) THEN GOTO STEP6

         Middle = (First + Last) ASR 1

         INC(Compares)
         IF Target = Search(Middle) THEN
            Last = Middle - 1
         ELSE
            First = Middle + 1
         ENDIF

         Length = Last - First + 1

         GOTO STEP2

      {STEP6}
         INC(Compares)
         ?You must check to see if Target is at First or Last.

      TCompares = TCompares + Compares
      DDisplay(2,TCompares/Count)
      ADisplay(2,TCompares/Count)
   NEXT Count

   GRETURN
END




SUBROUTINE ModBinary
?************************************************************************
?**  ModBinary  **                                         NC: 01/24/88 *
?************************************************************************
?*                                                                      *
?*    This routine performs a modified binary search for a randomly     *
?* generated # between 1 and 1793 while at the same time counting the # *
?* of comparisons it does to actual array elements.                     *
?*                                                                      *
?************************************************************************
   LOCAL
      INTEGER  First, Last, Middle, Length, Compares, TCompares
      INTEGER  Count, Target


   TCompares = 0
   DDisplay(3,0)
   ADisplay(3,0)

   FOR Count = 1 TO 1000
      First = 1
      Last = 1793
      Length = 1793
      Compares = 0
      Target = (RANDOM()\1793) + 1

      {STEP2}
         IF (Length <= 2) THEN
            INC(Compares)
            ?Check to see if Target is at First or Last.
            GOTO STEP6
         ENDIF

         Middle = (First + Last) ASR 1

         IF Target < Search(Middle) THEN
            INC(Compares)
            Last = Middle - 1
         ELSE IF Target > Search(Middle) THEN
            INC(Compares,2)
            First = Middle + 1
         ELSE
            INC(Compares,2)
            GOTO STEP6
         ENDIF

         Length = Last - First + 1

         GOTO STEP2

      {STEP6}

      TCompares = TCompares + Compares
      DDisplay(3,TCompares/Count)
      ADisplay(3,TCompares/Count)
   NEXT Count

   GRETURN
END



SUBROUTINE LED
?************************************************************************
?**  LED  **                                               NC: 01/24/88 *
?************************************************************************
?*                                                                      *
?*    This routine turns any of the screen LEDs on or off.              *
?*                                                                      *
?************************************************************************
   PARAMETER
      INTEGER  Which, State

   LOCAL
      INTEGER  X, Y


   X = #(SCR + 192)
   #(SCR + 192) = #(SCR + 208)
   #(SCR + 208) = X
   ^(SCR + 189) = 5

   WHEN Which IS

      [POWER]  X=300
               Y=17
      [BFLED]  X=7
               Y=111
      [BLED]   X=117
               Y=111
      [MBLED]  X=227
               Y=111

   ENDCASES



   WHEN State IS

      [ON]     COLOR_BOXFILL #10 (0,X-2,Y-1,X+2,Y+1)
               COLOR_BOXFILL #10 (0,X-1,Y-2,X+1,Y+2)
      [OFF]    COLOR_BOXFILL #2  (0,X-2,Y-1,X+2,Y+1)
               COLOR_BOXFILL #2  (0,X-1,Y-2,X+1,Y+2)

   ENDCASES


   ^(SCR + 189) = 1
   X = #(SCR + 192)
   #(SCR + 192) = #(SCR + 208)
   #(SCR + 208) = X

   GRETURN
END




SUBROUTINE CMOVE
?************************************************************************
?**  CMOVE  **                                             NC: 11/10/87 *
?************************************************************************
?*    This routine is used solely by InstallCopList.  It appends a MOVE *
?* instruction to the user copper list pointed to by UCopList.          *
?************************************************************************

   PARAMETER
      INTEGER  Address, Data


{BODY}
   &SYSLIB 1
      CMove(GraBase,UCopList,Address,Data)
      CBump(GraBase,UCopList)
   &SYSLIB 0

   GRETURN
END




SUBROUTINE CWAIT
?************************************************************************
?**  CWAIT  **                                             NC: 11/10/87 *
?************************************************************************
?*    This routine is used solely by the InstallCopList routine, it's   *
?* only purpose in life is to append a WAIT instruction to the user     *
?* defined copper list: UCopList.                                       *
?************************************************************************

   PARAMETER
      INTEGER  VertPos, HorzPos


{BODY}
   &SYSLIB 1
      CWait(GraBase,UCopList,VertPos,HorzPos)
      CBump(GraBase,UCopList)
   &SYSLIB 0

   GRETURN
END



SUBROUTINE DDisplay
?************************************************************************
?**  DDisplay  **                                          NC: 01/23/88 *
?************************************************************************
?*                                                                      *
?*    This routine displays a value in one of the three 7-segment       *
?* displays on the screen.                                              *
?*                                                                      *
?************************************************************************
   PARAMETER
      INTEGER  Meter, Num

   LOCAL
      INTEGER  Dig1, Dig2, Dig3, Dig4, DigData, X, Y, Ptr


   ?** Get pointer to screen location and corresponding data. **
      Ptr = SSDispLoc(Meter) + BP4
      WHEN Meter IS
            [1]   DigData = @Digits
            [2]   DigData = @Digits + 704
            [3]   DigData = @Digits + 1408
      ENDCASES


   ?** Get pointers to data for each character. **
      Dig4 = DigData + ((Num\10) LSL 6)
         Num = Num/10
      Dig3 = DigData + ((Num\10) LSL 6)
         Num = Num/10
      Dig2 = DigData + ((Num\10) LSL 6)
         Num = Num/10
      Dig1 = DigData + ((Num\10) LSL 6)

   ?** Blank leading 0's. **
      IF Dig1 = DigData THEN
         IF Dig2 = DigData THEN
            IF Dig3 = DigData THEN
               Dig1 = Dig2 = Dig3 = DigData + 640
            ELSE
               Dig1 = Dig2 = DigData + 640
            ENDIF
         ELSE
            Dig1 = DigData + 640
         ENDIF
      ENDIF

   ?** Draw it. **
      FOR X = 1 TO 24
         $Ptr+ = $Dig1
            INC(Dig1,2)
         $Ptr+ = $Dig2
            INC(Dig2,2)
         $Ptr+ = $Dig3
            INC(Dig3,2)
         $Ptr+ = $Dig4
            INC(Dig4,2)
         INC(Ptr,32)
      NEXT X

   GRETURN
END



SUBROUTINE ADisplay
?************************************************************************
?**  ADisplay  **                                          NC: 01/24/88 *
?************************************************************************
?*                                                                      *
?*    This routine moves the analog meters from there old position to   *
?* the new one specified by the caller.                                 *
?*                                                                      *
?************************************************************************
   PARAMETER
      INTEGER Meter, Num

   LOCAL
      INTEGER X,Y,X1,Y1,S,T, Bits, Lights, A, Off



?** Does caller want direct control of all meters. **
   IF Meter = All THEN
      COLOR_LINE #0 (0,50,105,(50+OldNum(1)-40),$(@Arc + (OldNum(1) ASL 1)))
      COLOR_LINE #1 (0,50,105,(50+Num-40),$(@Arc + (Num ASL 1)))
      COLOR_LINE #0 (0,160,105,(160+OldNum(2)-40),$(@Arc + (OldNum(2) ASL 1)))
      COLOR_LINE #1 (0,160,105,(160+Num-40),$(@Arc + (Num ASL 1)))
      COLOR_LINE #0 (0,270,105,(270+OldNum(3)-40),$(@Arc + (OldNum(3) ASL 1)))
      COLOR_LINE #1 (0,270,105,(270+Num-40),$(@Arc + (Num ASL 1)))
      OldNum(1) = OldNum(2) = OldNum(3) = Num
      GRETURN
   ENDIF

   Bits = OldBGBits(Meter)
   Lights = OldBGLights(Meter)
   A = OldBGVal(Meter)
   Off = OldBGOffset(Meter) + #(SCR + 204)


   X1 = CUMeter(Meter)
   Y1 = 105

   IF Num>1000 THEN Num=1000
   Num = FLOAT(Num)/12.5
   IF Num=OldNum(Meter) THEN GRETURN

?   S = (Num>OldNum(Meter)) - (Num<OldNum(Meter))
   IF Num>OldNum(Meter) THEN
      S = 1
   ELSE
      S = -1
   ENDIF

   FOR X = OldNum(Meter) TO Num STEP S
      Y = $(@Arc + (X ASL 1))
      COLOR_LINE #1 (0,X1,Y1,(X1+X-40),Y)

      IF S>0 THEN
         A = A ASR 1
         INC(Lights)
         INC(Bits)
         IF Bits = 9 THEN
            Bits = 1
            INC(Off,1)
            A = -1 AND FFFFFF80'16
         ENDIF
      ELSE
         A = A ASL 1
         DEC(Lights)
         DEC(Bits)
         IF Bits = 0 THEN
            Bits = 8
            DEC(Off,1)
            A = -1
         ENDIF
      ENDIF
     FOR T = Off TO Off+240 STEP 40
         ^(T) = A
         ^(T+1) = 0
     NEXT T


      FOR T = 0 TO FullDelay
      NEXT T

      COLOR_LINE #0 (0,X1,Y1,(X1+X-40),Y)
   NEXT X

   COLOR_LINE #1 (0,X1,Y1,(X1+X-40),Y)
   OldNum(Meter) = Num

   OldBGBits(Meter) = Bits
   OldBGLights(Meter) = Lights
   OldBGVal(Meter) = A
   OldBGOffset(Meter) = Off - #(SCR + 204)

   GRETURN
END


SUBROUTINE Toggle
?************************************************************************
?**  Toggle  **                                            NC: 01/25/88 *
?************************************************************************
?*                                                                      *
?*    Toggle the power switch.                                          *
?*                                                                      *
?************************************************************************

LOCAL
   INTEGER X,Y,TEMP,CurPlane


   CurPlane = #(SCR + 208) + 234
   FOR X = 1 TO 75 STEP 25
      FOR Y = X TO X+24
         TEMP = $CurPlane
         $CurPlane = Switch(Y)
         Switch(Y) = TEMP
         INC(CurPlane,40)
      NEXT Y
      IF X=1 THEN
         CurPlane = #(SCR + 196) + 234
      ELSE
         CurPlane = #(SCR + 192) + 234
      ENDIF
   NEXT X

   GRETURN
END



SUBROUTINE ShutDown
?************************************************************************
?**  ShutDown  **                                         NC: 01/25/88  *
?************************************************************************
?*                                                                      *
?*    Turns amp off, simulates power "thud".                            *
?*                                                                      *
?************************************************************************

LOCAL
   INTEGER  X


   Toggle()
   LED(POWER,OFF)

   COLOR_DEFINE #3 (Color7(1),Color7(2),Color7(3))
   COLOR_DEFINE #4 (Color7(1),Color7(2),Color7(3))
   COLOR_DEFINE #5 (Color7(1),Color7(2),Color7(3))
   COLOR_DEFINE #6 (Color7(1),Color7(2),Color7(3))

   COLOR_DEFINE #9 (Color1(1),Color1(2),Color1(3))
   COLOR_DEFINE #10 (Color2(1),Color2(2),Color2(3))

   DELAY(4)

   ADisplay(1,0)
   ADisplay(2,0)
   ADisplay(3,0)

   DELAY(5)
   FOR X = 0 TO 15
      ADisplay(All,X)
   NEXT X
   DELAY(2)
   FOR X = 15 TO 0 STEP -1
      ADisplay(All,X)
   NEXT X

   ^(SCR + 189) = 5

   DELAY(10)

   WINDOW_CLOSE #1
   SCREEN_CLOSE #1

   GRETURN
END
SUBROUTINE Startup
?************************************************************************
?**  Startup  **                                           NC: 01/23/88 *
?************************************************************************
?*                                                                      *
?*    This routine loads in the main screen from an iff file, decomp-   *
?* resses it, and displays it on a screen that is opens.  It then waits *
?* for the user to turn on the amplifier with the mouse.                *
?*                                                                      *
?************************************************************************

LOCAL
   INTEGER  X, Z, Line, CP, CurPlane, PTR, FEnd, PicFile, Handle
   INTEGER  MouseX, MouseY, BP(5), Color0, Color17, Color18
   BYTE     Y
   TEXT*20  FileName
   REAL     A


   DOSBase  = OPENLIB("dos.library",0)
   IntBase  = OPENLIB("intuition.library",0)
   GraBase  = OPENLIB("graphics.library",0)

?** Go get the picture off the disk. **
   PicFile  = ALLOCATE(20000)
   FileName = "df1:DS1.Screen" & CHAR(0)

   &SYSLIB 1
      Handle = Open(DOSBase, @FileName, 1005)
      FEnd   = Read(DOSBase, Handle, PicFile, 20000)
               Close(DOSBase, Handle)
   &SYSLIB 0


?** Open a screen and get pointers to its bitplanes. **
   SCR = SCREEN #1 (0,200,5,1,0)
   FOR X = 1 TO 5
      BP(X) = #(SCR + 192 + ((X-1) LSL 2))
   NEXT X
   BP4 = BP(4)
   BP5 = BP(5)
   ViewPort = SCR + 44


?** Open a window so I can change sys colors. **
   WND = WINDOW #1(0,0,320,200,0,0,0,0,-1,-1,0,0,1)
   CURS_INV


?** Get the pictures natural colors and install them. **
   PTR = PicFile + 30'16

   COLOR_DEFINE #0 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   Color0 = (^PTR LSL 4) OR ^(PTR + 1) OR (^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #1 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   Color1(1) = ^PTR LSR 4
   Color1(2) = ^(PTR + 1) LSR 4
   Color1(3) = ^(PTR + 2) LSR 4
      INC(PTR,3)
   COLOR_DEFINE #2 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   Color2(1) = ^PTR  LSR 4
   Color2(2) = ^(PTR + 1) LSR 4
   Color2(3) = ^(PTR + 2) LSR 4
      INC(PTR,15)
   COLOR_DEFINE #3 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   COLOR_DEFINE #4 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   COLOR_DEFINE #5 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   COLOR_DEFINE #6 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   COLOR_DEFINE #7 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   Color7(1) = ^PTR LSR 4
   Color7(2) = ^(PTR + 1) LSR 4
   Color7(3) = ^(PTR + 2) LSR 4
      INC(PTR,3)
   COLOR_DEFINE #8 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #9 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #10 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #11 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #12 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #13 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #14 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #15 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #16 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #17 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   Color17 = (^PTR LSL 4) OR ^(PTR + 1) OR (^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #18 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
   Color18 = (^PTR LSL 4) OR ^(PTR + 1) OR (^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #19 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #20 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #21 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #22 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #23 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #24 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #25 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #26 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #27 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #28 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #29 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #30 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #31 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)


?** Install a user copper list to do some color masking. **
   UCopList = ALLOCATE_WITH(12,10001'16)

   ?** Wait until the video beam is @ line 120. **
      CWAIT(120,0)
   ?** Change 2 of the screen colors. **
      CMOVE(1A2'16,Color0)
      CMOVE(1A4'16,Color0)

   ?** Wait 'til the video beam is past the area. **
      CWAIT(140,0)
   ?** Change the 2 colors back. **
      CMOVE(1A2'16,Color17)
      CMOVE(1A4'16,Color18)

   ?** Wait forever. *8
      CWAIT(10000,255)

   ?** Install it. **
      #(ViewPort + 20) = UCopList
      &SYSLIB 1
         RethinkDisplay(IntBase)
      &SYSLIB 0
      DELAY(1)



?** TRY to decompress this stupid picture properly. **
   PTR = PicFile + 148'16
   FEnd = FEnd + PicFile
   Line = 40
   CP = 1
   CurPlane = BP(1)

   WHILE PTR<FEnd
      Y = ^PTR
      INC(PTR)

      IF Y<0 THEN
         Y = -Y
         Z = ^PTR
         INC(PTR)
         FOR X = 0 TO Y
            ^CurPlane+ = Z
         NEXT X
         Line = Line - Y - 1
      ELSE
         FOR X = 0 TO Y
            ^CurPlane+ = ^PTR
            INC(PTR)
         NEXT X
         Line = Line - Y - 1
      ENDIF

      IF Line <= 0 THEN
         Line = 40
         BP(CP) = CurPlane
         INC(CP)
         IF CP=6 THEN CP=1
         CurPlane = BP(CP)
      ENDIF
   ENDWHILE


?** Trick the Blitter into thinking there's only 1 bitplane (#5).  This
?**   should effectively allow the needles of each meter to be draw over
?**   the background without destroying it. **
   ^(SCR + 189) = 1
   X = #(SCR + 192)
   Z = #(SCR + 208)
   #(SCR + 192) = Z
   #(SCR + 208) = X


?** Wait for the user to turn the amp on.
   REPEAT
      WHILE BTST(6,^BFE001'16)
      ENDWHILE
      MouseX = $(SCR + 18)
      MouseY = $(SCR + 16)
   UNTIL (MouseX-271)>0 AND (MouseX-287)<0 AND (MouseY-10)>0 AND (MouseY-30)<0


?** Turn the switch and POWER light on. **
   Toggle()
   LED(POWER,ON)


?** Delay for effect. **
   DELAY(3)


?** Turn the lights on in the meters. **
   PTR = PicFile + 39'16
   COLOR_DEFINE #3 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #4 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #5 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #6 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)
      INC(PTR,3)
   COLOR_DEFINE #7 (^PTR LSR 4, ^(PTR + 1) LSR 4, ^(PTR + 2) LSR 4)


?** Turn the 7-segment displays on. **
   DDisplay(1,0)
   DDisplay(2,0)
   DDisplay(3,0)


?** Dispose of the compressed file. **
   PicFile = DEALLOCATE(20000,PicFile)


?** Fake an amp warmup cycle. **
   DELAY(6)
   FOR X = 0 TO 80 STEP 4
      ADisplay(All,X)
   NEXT X
   DELAY(10)
   FOR A = 80 TO 0 STEP -.5
      ADisplay(All,INT(A))
   NEXT A


GRETURN
END

