Classic Computer Magazine Archive COMPUTE! ISSUE 37 / JUNE 1983 / PAGE 168

Apple Shape Generator
J, F Johnson

The Apple computer allows shapes to be manipulated from within a BASIC program. Although shapes are very useful in two-dimensional dynamic graphics, the process of creating shapes and entering them into a shape table is tedious, and errors are exceedingly difficult to correct. This program simplifies the process of defining a shape. All required binary to hexadecimal conversions require no user intervention and a shape table is automatically constructed, with each new shape added to the current table.

Many of the shape-drawing routines currently available for the Apple allow a shape to be created within a rectangular drawing area, with a bit map of this entire area, then stored as the shape. This technique is fine for creating relatively small shapes. However, as the size of the shape increases (so that the rectangular area the size of either hi-res page is required to enclose the shape), the amount of wasted space (i.e., bytes which are "off" and represent only the background) becomes considerable. A bit map of a shape requiring a rectangular area of this size would require 7-8 K.
    This program creates shapes in the manner explained in the Applesoft manual (Chapter 9). The head-to-tail vector method is used to initially define the shape. These vectors are then "unwrapped" and sequentially combined in pairs for conversion from their individual binary codes into equivalent hexadecimal code. Each hexadecimal byte represents one byte in the shape definition. The shape is then added to the table in memory with the table's index also updated. Shapes which would have required up to 8K in a table have been reduced to less than 1K using this program.

Capabilities Of Key Shape Maker
The following can be accomplished with Key Shape Maker:

1) Construct a shape table comprised of 1-255 shapes.
2) Create a table with a maximum length of 6K.
3) Alter any shape after it has been entered into the table. Also, add "buffer bytes" at the end of each shape definition so that any shape can be slightly enlarged relative to its original
definition.
4) Correct mistakes which occur while entering vectors during a shape definition by erasing them in a sequential fashion.
5) View all the shapes in the current table (using the game paddles).
6) Display any particular shape, with the effect of ROT and SCALE variations (using the game paddles) on the shape immediately displayed on the hi-res screen.
7) Once a shape table is BSAVEd to diskette using this utility, it may be BLOADed with the utility and the stored shapes redefined and new shapes added (assuming the table does not contain the maximum number of shapes originally designated).
8) The current shape table in RAM can be destroyed, and a new table created or an old table BLOADed into memory.

Use An EXEC File To Initialize
The entire program is written in Applesoft. The following program creates a text file, "Key Shape Loader", which reassigns the beginning of the program pointer (104, 103) and then RUNS the program.

Program 1.

5  REM KEY SHAPE LOADER MAKER
10 D$ = CHR* (4)
15  PRINT D$"MON C,I,O"
17  PRINT D$"DELETE KEY SHAPE LOADER"
20  PRINT D$"OPEN KEY SHAPE LOADER"
30  PRINT D$"WRITE KEY SHAPE LOADER"
40  PRINT "POKE 104,96"
50  PRINT "POKE 103,1"
60  PRINT "POKE 24576,0"
70  PRINT "RUN KEY SHAPE MAKER"
80  PRINT D$"CLOSE KEY SHAPE LOADER"
90  END

    By EXECing the text file Key Shape Loader, the required POKES are completed, and then the Applesoft program "Key Shape Maker" is RUN.

Use Of RAM By "Key Shape Maker"
The Applesoft program is LOADed at $6001 (24577), just above the second hi-res page of graphics. The second hi-res page is used for the temporary storage of vectors that define the current shape. These vectors are then paired and converted into their equivalent hexadecimal code, with the resulting hex code defining the shape stored on the second hi-res page. If the shape is to be saved, the hex code is then transferred to the shape table. The creation and display of all shapes utilizes the first hi-res page. The shape table is stored at $800 (2048), and its length may not exceed $2000 (8196) since the first hi-res page is used for display purposes.

Execution
The user is initially prompted for the number of shapes that will be entered into the table. Since extra shapes are invariably required at a future date, it is always best to enter a number larger than what is currently estimated. The minimum number is 1, and the maximum is 255. Since the table need not be completed at one setting, the partially constructed table can be BSAVEd, then BLOADed at a future date, with additional shapes added (up to the original number that was userspecified) or current table shapes redefined.
    This maximum number of shapes is then POKEd into $801. Room for the shape table index (which immediately follows starting at $802) is then allocated. The index stores the locations of all shapes relative to the start of the table ($800). The index must contain two bytes for each stored shape. If the estimated number of shapes to be stored in this table is low, it will not be possible to exceed this limit since room in the table for the index can not be changed using this program. Location $800 initially contains a value of zero, and is incremented by one upon the addition of each shape to the table.
    The shapes are created using two different sets of four keys. Plotting vectors are entered using the I, K, M, and J keys, while the nonplotting vectors are entered using the E, D, X, and S keys. Both sets of keys are arranged on the keyboard in a north-east-south-west fashion, with the righthand set for plotting and the left-hand set for nonplotting. The back arrow key (<-) may be used to sequentially erase vectors starting with the last one entered, and is very useful for correcting any mistakes. The keystroke "!" (a shift-1) terminates the shape definition.
    Prior to the actual construction of the shape, a "dot-cursor" is positioned on the first hi-res screen. This is the point at which the shape definition is initiated. The shape is then displayed as it is constructed, using the previously defined keystrokes. Due to the algorithm used to display the shape as it is defined, any nonplotting vectors which cross any existing outline of the shape will result in the boundary being erased where the crossover occurs.
    However, when the final shape is displayed for verification, it will exhibit the contiguous boundary that was originally constructed. Also displayed during the construction of the shape are the current x and y coordinates of the "dotcursor," the three-digit binary code of each vector as it is entered, and the maximum number of bytes which may be used to define the present shape.
    When the definition of the shape is terminated, the keystroke vectors are converted to hexadecimal code, with the resulting shape displayed prior to its storage in the table. If the user chooses to save the shape, he or she appends it to the current table, updates the corresponding index locations, and increments location $800 by one. If the shape is not saved, the defining of additional shapes, simply continues.

Applesoft Shape Table Commands
Several subroutines in this program allow the user to experiment with several shape table commands and to view the result. This was purposely included to aid the user in exploring the capabilities (as well as the limitations) of shapes within Applesoft. This will perhaps facilitate inclusion of shape tables within programs.
    The SCALE command allows the expansion of a defined shape. Since the originally defined shape is constructed using the smallest SCALE value, a figure may only be expanded using this command. It will soon be discovered, however, that the contiguous boundary of a shape may become segmented when its size is enlarged through SCALEing, and may rapidly become unrecognizable. This can usually be overcome by redefining the same shape boundary using a different sequence of plotting/nonplotting vectors. The ability to redefine any given shape will allow the user to experiment.
    Rotations in the plane of the screen are controlled by the ROT command. An inverse relationship exists between the number of unique rotational values defined by the ROT command and the SCALE command. Increasing ROT from 0 to 64 will rotate it 360 degrees about the origin. As the value for SCALE increases from 0, more unique rotational values are recognized between the ROT values of 0 and 64, and hence the incremental rotational angle decreases. By making the original shape very small, and then expanding it using the SCALE command, a smaller angle of rotation can be realized between the ROT values of 0 and 64. The values for both of the commands may be varied for a chosen shape, with the effects on the shape displayed on the screen.
    A shape may be displayed from Applesoft using either the DRAW or XDRAW commands. The XDRAW command simply complements the current color of the shape at its present location and is very convenient for displaying and erasing shapes. The DRAW command requires that HCOLOR be changed from a value of 3 to 0 if the shape is to first be drawn and then erased. These commands may also display the same shape differently. If any nonplotting vectors cross the boundary of plotting vectors in the original shape definition, the DRAW command (HCOLOR=3) will display a contiguous shape.
    The XDRAW command, however, displays the shape with any regions of plotting/nonplotting vector overlap being effectively erased. This should be taken into consideration when originally defining the shape boundary, since one of the two display techniques may be preferred in the Applesoft program which uses the shapes. The shape display for verification purposes (prior to appending the shape to the current table) is displayed using DRAW (HCOLOR=3). During viewing of a shape in the current table with ROT and SCALE variations, the shape is drawn and erased using XDRAW.

Using A Shape Table
Key Shape Maker creates a shape table starting at $800 (2048) in RAM. It maybe BLOADed into another region if there exists a conflict with the storage of the controlling Applesoft program or a machine language program which must occupy this region. There are two DOS entry points which store both the starting address and length of a BLOADed file. Since the user determines the starting address of a binary file, only the length must be determined. This is accomplished in the following manner.
    After BSAVEing your shape table to diskette, BLOAD it back into memory (this may be done in direct execution or under Key Shape Maker control). If the shape table has been loaded by an Applesoft program, press the reset button. Now enter the following as a direct execution instruction, where <ret> simply designates pressing the return key.

PRINT PEEK(43616)+PEEK(43617)*256 <ret>

    The base ten number that appears on the screen immediately after this instruction is the length of the shape table (see Appendix E of the DOS manual, DOS Entry Points And Schematics). Using this additional piece of information, the user is offered some flexibility in BLOADing the shape table into various regions of RAM. For example, a shape table of byte length 350 may be BLOADed at location 24577 (immediately above the second hi-res page) with the following instruction in an Applesoft statement.

100 PRINT CHR$(4)"BLOAD SHAPE TABLE-1,A24577,L350"

    The final piece of information which must be supplied is the location of the shape table. The pointer designating the beginning of the current shape table is located on the zero page of memory, and is comprised of the locations $E8 (232) and $E9 (233). The integer value obtained by dividing the starting address by 256 is POKEd into 233, with the remainder POKEd into 232 (i.e., 24577/ 256=96 with a remainder of 1).

110 POKE 233,96:POKE 232,1

Your Applesoft program will now be able to effectively use the shape table currently residing in RAM.

Program 2.

5  REM  KEY SHAPE MAKER
60  REM    TS=START OF SHAPE TABLE///VC=MARK
     ER USED IN DISPLAY OF 6 DIGITS REPRESEN
     TING 2 VECTORS///VS=MARKER FOR START OF
      TEMPORARY STORAGE FOR VECTOR TABLE AND
      ENSUING TEMPORARY STORAGE DERIVED SHAP
     E///16395=START OF TEMPORARY SHAPE TABL
     E
70 A$ = "PRESS ! TO STOP DRAWING SHAPE."
80 TS = 2048: POKE TS,0:VC = 16389:VS = 1639
     6:LI = 2050:MI = 2051:D$ = CHR$ (4)s GOTO
     4000
100  HCOLOR= 3: HPLOT X,Ys FOR J = 1 TO 20: NEXT
     J: HCOLOR= 0: HPLOT X,Y:X = PDL (0) /
     .913:Y = PDL (1) / 1.6: IF PEEK ( - 1
     6287) > 127 OR PEEK ( - 16286) > 127 THEN
      RETURN
105  GOTO 100
110 S1 = INT (1 + PDL (0) * ( PEEK (TS) -
     1) / 240): ROT= 0: HCOLOR= 31 SCALE= 1:
      RETURN
115 S2 = INT (1 + PDL (0) * ( PEEK (TS) -
     1) / 240): RETURN
120 XDRAW Sl AT X,Y: VTAB 24: HTAB 1: CALL
     - 868: PRINT "SHAPE #"S1".";
125  GOSUB 115: IF PEEK ( - 16287) > 127 THEN
      RETURN
130  IF S2 < > Sl THEN XDRAW S1 AT X,Y:S1 =
     S2: GOTO 120
135 GOTO 125
140 GOSUB 110
145 VTAB 5: HTAB 1: CALL - 868: PRINT "SHA
    PE #"81"."
150 GOSUB 115: IF S2 < > Sl THEN Sl = S2: GOTO
    145
152 IF PEEK ( - 16287) > 127 THEN RETURN
154 GOTO 150
158 S1 = INT ( PDL (1) * 7 / 240): RETURN
159 S2 = INT ( PDL (1) * 7 / 240): RETURN
160 GOSUB 158
162 VTAB 10: HTAB 1: CALL - 868: PRINT "HC
    OLOR="S1 "."
164 GOSUB 159: IF S2 < > S1 THEN S1 = S2: GOTO
    162
166 IF PEEK ( - 16286) > 127 THEN RETURN
168 GOTO 164
170 GOTO 166
172 Rl = PDL (0) / 3:S1 - PDL (1) / 3: RETURN
173 R2 = PDL (0) / 3:S2 = PDL (1) / 3: RETURN
174 GOSUB 172
175 HCOLOR= HC: ROT= R1: SCALE= S1: DRAW SH
     AT XI,YI: VTAB 24: HTAB 1: CALL - 868
    : PRINT "ROT=" INT (R1) SPC( 8)"SCALE="
     INT (S1);
176 GOSUB 173: IF R2 <    > R1 OR S2 <    > Sl THEN
    Rl = R2:S1 = S2: CALL 62450: GOTO 175
177 IF PEEK ( - 16287) > 127 OR PEEK ( -
    16286) > 127 THEN RETURN
178 GOTO 176
200 POKE TS + 1, VAL (NS$): RETURN : REM M
    AXIMUM NUMBER OF SHAPES THAT CAN BE ENT
    ERED INTO THIS TABLE
203 PA = 256 * PEEK (MI) + PEEK (LI) + TS:
      RETURN
205 PA = TS + 4 + 2 * VAL (NS$): RETURN : REM
        IS LOCATION IN TABLE WHERE FIRST SHA
     PE WILL BE SAVED
210 LS = TS + 2 * SH:MS = TS + 1 + 2 * SH:DD
      = 256 * ( PEEK (MS + 2) - PEEK (MS)) +
     ( PEEK (LS + 2) - PEEK (LS)): RETURN
212 LI = TS + 2 - ( PEEK (TS) + 1):MI = LI +
     1: RETURN : REM   INIT INDEX FOR TABLE
     THAT HAS BEEN LOADED
215 LI = LI + 2:MI = MI + 2: RETURN : REM
     INCREMENT INDEX LOCATION FOR NEXT SHAPE
220 LI = LI - 2:MI = MI - 2: RETURN : REM
     DECREMENT INDEX LOCATION FOR FIRST SHAP
     E TO BE DRAWN IN LOADED OR ALTERED TABL
     E
225 IP = VS: RETURN : REM INITIALIZE LOCATI
     ON WHERE PLOTTED VECTORS ARE STORED TEM
     PORARILY UNTIL THEY ARE CONVERTED INTO
     A SHAPE
230 N = VS + 1:SL = VS + 1: RETURN : REM IN
     ITIALIZE TWO COUNTERS WHICH ARE USED DU
     RING THE CONVERSION OF STORED VECTORS I
     NTO A SHAPE
235 PA = TS + 256 * PEEK (MS) + PEEK (LS):
      RETURN : REM LOCATION IN TABLE OF STA
     RT OF NEXT SHAPE
240 POKE LI, INT ((((PA - TS) / 256) - INT
    ((PA - TS) / 256)) * 256 + .5): POKE MI
    , INT ((PA - TS) / 256): RETURN : REM
      POKE STARTING LOCATION FOR GIVEN SHAP
     E IN APPROPRIATE INDEX LOCATION
250 A = 0:B = 0:C = 0: RETURN : REM    INITIA
     LIZE A,B,C TO ZERO
255 L = IP - VS:K = INT (L / 2) + INT ((L /
     2 - INT (L / 2)) * 2 + .05): RETURN : REM
      L=#BYTES CONTAINING VECTORS///K=#BYTES
      REQUIRED TO STORE SHAPE;l SHAPE BYTE P
     ER 2 VECTOR BYTES
260 POKE 233,64: POKE 232,9: POKE 16393,l: POKE
    16395,4: POKE 16396,0: RETURN : REM D
    EFINE UNIT SHAPE TABLE WHERE TEMPORARIL
    Y DEFINED SHAPE EXISTS
265 POKE 233,8: POKE 232,0: RETURN : REM L
    OCATION OF SHAPE TABLE
270 RS = PEEK (TS + 1) - PEEK (TS): RETURN
     : REM RS=# OF SHAPES THAT MAY STILL B
     E ENTERED INTO SHAPE TABLE
299 REM PLOT/ERASE POINT AT CURRENT X,Y UN
    TIL KEY PRESS OCCURS.
300 XO = X:YO = Y: HCOLOR= 3: HPLOT XO,YO: FOR
     J = 1 TO 20: NEXT J: HCOLOR= 0: HPLOT X
     O,YO: FOR J = 1 TO 20: NEXT J: IF PEEK
     ( - 16384) < 128 THEN 300
310 HCOLOR= 3: POKE - 16368,O:Z = PEEK ( -
    16384): RETURN
324 REM   PLOT PRESENT POINT IF ENTERED VEC
    TOR IS A PLOT-THEN-MOVE VECTOR
325 HCOLOR= 3: HPLOT XO,YO: RETURN
329 REM ERASE PREVIOUS POINT PLOTTED
330 HCOLOR= 0: HPLOT XO,YO: RETURN
349 REM EVALUATE KEY PRESS IN TERMS OF NEW
     X,Y COORDINATES.
350 Fl = 0
352  IF Z = 73 OR Z = 69 THEN Y = Y - 1: GOSUB
     362: RETURN : REM MOVE UP
354  IF Z = 75 OR Z = 68 THEN X = X + 1: GOSUB
     364: RETURN s REM    MOVE RIGHT
356  IF Z = 77 OR Z = 88 THEN Y = Y + 1: GOSUB
     366: RETURN : REM MOVE DOWN
358  IF Z = 74 OR Z = 83 THEN X = X - 1: GOSUB
     368: RETURN : REM   MOVE LEFT
360 F1 = 1: RETURN : REM   FLAG Fl SET TRUE
     IF NO U,R,D,L MOVE
362  IF Y < 0 THEN Y = 0:F1 = 1
363  RETURN
364  IF X > 279 THEN X = 279:Fl = 1
365  RETURN
366  IF Y > 159 THEN Y = 159:F1 = 1
367  RETURN
368  IF X < 0 THEN X = 0:Fl = 1
369  RETURN
399  REM EVALUATE 3 DIGIT BINARY EQUIVALENT
      OF INDIVIDUAL VECTOR
400 F1 = 0: IF Z = 73 THEN A = 1:B = 0:C = 0
     : RETURN
402  IF Z = 75 THEN A = 1:B = 0:C = 1: RETURN

404  IF Z = 77 THEN A = l:B = 1:C = 0: RETURN

406  IF Z = 74 THEN A = 1:B = l:C = 1: RETURN

408  IF Z = 69 THEN A = 0:B = 0:C = 0: RETURN

410  IF Z = 68 THEN A = 0:B = 0:C = 1: RETURN

412  IF Z = 88 THEN A = 0:B = 1:C = 0: RETURN

414  IF Z = 83 THEN A = 0:B = 1:C = 1: RETURN

418 F1 = 1: RETURN
424  REM PRINT PRESENT COORDINATES OF X,Y
425  VTAB 21: HTAB 1: CALL - 868: PRINT "X=
    "X,"Y="Y: RETURN
449  REM ERASE CURRENT POINT AND MOVE BACK
     ONE POINT
450 PP = PEEK (IP): IF IP = VS THEN RETURN
     : REM CAN'T ERASE PAST ORIGIN OF SHAPE

455  IF PP = 0 OR PP = 4 THEN Y = Y + 1: GOSUB
     475: RETURN
460  IF PP = 1 OR PP = 5 THEN X = X - 1: GOSUB
     475: RETURN
465  IF PP = 2 OR PP - 6 THEN Y = Y - 1: GOSUB
     475: RETURN
470  IF PP = 3 OR PP = 7 THEN X - X + is GOSUB
     475: RETURN
475 XO = X:YO = Y: GOSUB 330: POKE IP,0:IP =
     IP - 1: RETURN
499  REM POKE VECTOR INTO RAM LOCATION IP
500 IP = IP + 1: POKE IP,4 * A + 2 * B + C: RETURN
509  REM  POKE BINARY EQUIVALENT OF VECTOR M
     OVE
510 P(1 + I * 3) = A:P(2 + I * 3) = B:P(3 +
     I * 3) = C
515  IF I = 1 THEN FOR J = 0 TO 5: POKE 187
     2 + J,48: NEXT J: FOR J = 0 TO 2s POKE
     1875 + J,P(4 + J) + 48: NEXT J: RETURN

520  FOR J - 0 TO 2: POKE 1872 + J,P(1 + J) +
     48: NEXT J: RETURN
525  FOR J = 1 TO 6:P(J) = 0: NEXT J: RETURN

600  HGR2 : HGR : SCALE= 1: ROT= 0: HCOLOR=
     3:XX = 139:YY = 80:X = XX:Y = YY: RETURN
     : REM    HI-RES INITIALIZATION
700 BL = 8190 - PA:DI = 24576 - 16396:VL = D
     I: RETURN : REM NEW TABLE BYTE LIMITS
710 NS = PEEK (2048):LI = TS + 2 * (NS + 1)
     :MI = TS + 1 + 2 * (NS + 1):PA = TS + 2
     56 * PEEK (MI) + PEEK (LI)
720 BL = 8190 - PA: IF DI < 2 * (8190 - PA) THEN
     VL = DI: RETURN
730 VL = 2 * (8190 - PA): RETURN
765 Fl - 0: IF VL < 100 THEN F1 = 1
767  RETURN
770 F2 = 0: VTAB 21: PRINT "THERE ARE "8190 -
     PA" BYTES REMAINING FOR MORE": PRINT "S
     HAPES IN CURRENT TABLE IF YOU HAVE NOT
     CONSTRUCTED THE LAST SHAPE."
775  IF 8190 - PA < 100 THEN PRINT "NO MORE
      SHAPES MAY BE ADDED TO CURRENT TABLE.
     ":F2 = 1
780  RETURN
800 F3 = 0:VL = VL - 1: VTAB 21: HTAB 33: CALL
      - 868: PRINT VL
805  IF VL < 200 THEN VTAB 22: HTAB 1: PRINT
     "ONLY "VL - 190" MOVES LEFT.";: FOR J =
     1 TO 1000: NEXT J: HTAB 1: CALL - 868:
      IF VL < = 191 THEN F3 = 1
810  RETURN
975  VTAB 24: HTAB 5: CALL - 958: PRINT "PR
     ESS ANY LETTER TO CONTINUE.";: SET Z$:J
      = FRE (0): RETURN
999  REM INITIALIZE SHAPE TABLE PARAMETERS
1000  TEXT : HOME : PRINT  TAB( 5);"THE NUMB
     ER OF SHAPES THAT MAY BE    ENTERED IN
     A SHAPE TABLE IS IN THE RANGEOF 1-255.
      IT IS ALWAYS BEST TO ALLOW   EXTRA ROO
     M FOR ADDITIONAL SHAPES YOU MAYWISH TO
     INCLUDE IN THE FUTURE."
1010  INPUT "     ENTER A NUMBER BETWEEN 1 A
     ND 255,  THEN PRESS RETURN.";NS$: IF VAL
     (NS$) < 1 OR VAL (NS$) > 255 THEN 1000

1020  GOSUB 200: REM    POKE MAX # OF SHAPES
     THAT CAN BE ENTERED INTO THIS TABLE
1030  GOSUB 205: REM INITIAL RAM LOCATION F
     OR FIRST SHAPE
1040  GOSUB 240: REM STARTING POINT OF FIRS
     T SHAPE AND POKE INTO INDEX
1050  GOSUB 700: REM BL,DI,VL
1055  RETURN
1060  GOSUB 250: REM INITIALIZE COMPONENTS
     OF VECTOR MOVE
1070  GOSUB 600: REM HI-RES INIT
1080  RETURN
1200  TEXT : HOME : PRINT TAB( 5);"BEFORE A
     CTUALLY DRAWING A SHAPE,   THE BLINKIN
     G DOT MAY BE MOVED TO ANY   POSITION O
     N THE SCREEN. USE THE E,S,D  AND X KEY
     S FOR DOT POSITIONING ONLY."
1205  PRINT "PRESS ! WHEN READY TO DRAW A SH
     APE."
1210  PRINT TAB( 5);"THE SHAPE YOU ARE TO D
     RAW MAY THEN BE COMPRISED OF PLOTTING
     AS WELL AS NON PLOTTING VECTOS. USE TH
     E E,S,D AND X   KEYS FOR NONPLOTTING VE
     CTORS, AND THE   I,J,K AND M KEYS FOR P
     LOTTING VECTORS."
1220  PRINT "THE LEFT ARROW KEY (<-) MAY BE
     USED TO ERASE MISTAKES, AND THE ! KEY
     TO TERM- INATE THE SHAPE.": PRINT
1240  PRINT TAB( 1);"-NONPLOTTING-"; SPC( 9
     );"-PLOTTING-"
1250  PRINT TAB( 2);"E-MOVE UP" SPC( 7)"I-P
     LOT THEN MOVE UP": PRINT TAB( 2);"S-MO
     VE LEFT" SPC( 5)"J-PLOT THEN MOVE LEFT"
1260  PRINT TAB( 2);"D-MOVE RIGHT" SPC( 4)"
     K-PLOT THEN MOVE RIGHT": PRINT TAB( 2)
     :"X-MOVE DOWN" SPC( 5)"M-PLOT THEN MOVE
      DOWN"
1270  PRINT TAB( 12);"<- ERASER": PRINT TAB(
     12);"!  STOP"
1280  GOSUB 975
1285  HOME : VTAB 23: PRINT "PRESS ! WHEN YO
     U ARE READY TO DRAW YOUR SHAPE.": GOSUB
     600: GOSUB 425
1290  GOSUB 300: IF Z = 33 THEN XI - X:YI =
     Y: HOME : RETURN
1300  GOSUB 350: GOSUB 425: GOTO 1290
1350  GOSUB 225: GOSUB 425: GOSUB 525:I = 0:
      GOSUB 515: VTAB 22: HTAB 1: PRINT A$: IF
      NOT F5 THEN GOSUB 720: GOSUB 800: IF
     F3 THEN RETURN
1360 I = 1 - I: REM TOGGLE
1370  IF FS THEN HTAB 1: VTAB 24: CALL - 8
     68: PRINT "YOU HAVE UP TO "2 * DD - 3 -
     (IP - 16394)" MOVES LEFT.";: IF 2 * DD -
     3 - (IP - 16394) = 0 THEN RETURN
1380  GOSUB 300: IF Z = 33 THEN RETURN
1390  IF Z = 8 THEN GOSUB 450: GOSUB 425: GOTO
     1360: REM ERASE LAST MOVE
1400  IF Z = 69 AND I - 0 THEN VTAB 22: HTAB
     1: PRINT "THIS MOVE HAS NO EFFECT ON TH
     E SHAPE.";: FOR J = 1 TO 2000: NEXT J: HTAB
     1: CALL  - 868: PRINT A$: GOTO 1370
1405  GOSUB 350: IF F1 THEN 1370: REM    EVAL
      KEY PRESS FOR NEW X,Y : SET FLAG F1 IF
      ILLEGAL
1410  GOSUB 400: REM EVALUATE 3 DIGIT BINAR
     Y EQUILVALENT OF KEY PRESS
1420  GOSUB 500: REM SAVE VECTOR MOVE WITH
     POKE
1430  GOSUB 510: REM DISPLAY 'ACCUMULATOR'
     WITH TEXT POKES
1440  GOSUB 425: REM    PRINT NEW X,Y COORDS
     TO SCREEN
1450  IF Z > 72 AND Z < 78 THEN GOSUB 325: REM
       PLOT POINT ON HI-RES FOR APPROPRIATE
     PLOTTING VECTOR
1455  IF NOT F5 THEN GOSUB 800: IF F3 THEN
      RETURN
1460  GOTO 1360
1500  GOSUB 230
1510  GOSUB 255
1520  FOR J = 1 TO K: POKE N,( PEEK (SL) + 8
      *  PEEK (SL + 1)):SL = SL + 2:N = N +
     1: NEXT J: POKE N,0: REM POKE SHAPE 'O
     N TOP OF' VECTORS
1530  GOSUB 260: HGR : HCOLOR- 3: DRAW 1 AT
     XI,YI: GOSUB 265
1540  HOME : VTAB 21: PRINT "DO YOU WISH TO
     SAVE THIS SHAPE (Y/N)?";: SET Z$: IF Z$
      < > "Y" AND Z$ < > "N" THEN 1540
1545  IF F5 THEN RETURN
1550  IF Z$ = "N" THEN RETURN
1560  FOR J = N + 1 TO N + 2 + .25 * (N - VS
      + 1): POKE J,0: NEXT J: REM   EXPAND S
     HAPE 25% BY ADDING ZEROS AT END
1570 N = J - 1: FOR J = VS + 1 TO N: POKE PA
     , PEEK (J):PA = PA + 1: NEXT J: REM   T
     RANSFER SHAPE FROM TEMPORARY LOCATION T
     O SHAPE TABLE
1580 NS = PEEK (TS):NS = NS + 1: POKE TS,NS
     : REM INCREASE # SHAPES IN INDEX BY 1

1590  GOSUB 215: GOSUB 240:  REM  POKE DATA
     INTO THIS INDEX LOCATION///INCREMENT IN
     DEX LOCATIION OF NEXT SHAPE
1610  RETURN
1700  GOSUB 600: HOME : VTAB 21: PRINT "USE
     THE GAME PADDLES TO POSITION THE DOTAT
     WHICH POINT THE SHAPE WILL BE DRAWN. PR
     ESS EITHER BUTTON WHEN READY TO VIEW S
     HAPEB.";
1720 X = 140:Y = 80: GOSUB 100:NS = PEEK (2
     048): HOME : VTAB 21: PRINT "USE THE X
     GAME PADDLE TO VIEW ALL SHAPESIN CURREN
     T TABLE. PRESS BUTTON WHEN  FINISHED
      VIEWING.": GOSUB 110: GOSUB 120: RETURN

1750  TEXT : HOME : PRINT TAB( 5);"THE FOLL
     OWING SEQUENCE WILL BE    FOLLOWED IN
      VIEWING A SHAPE."
1755  PRINT : PRINT "1) INPUT SHAPE NO. USIN
     G X GAME PADDLE.": PRINT : PRINT "2) IN
     PUT HCOLOR USING Y GAME PADDLE.": PRINT
     : PRINT "3) MOVE SHAPE TO DESIRED POSIT
     ION.": PRINT : PRINT "4) USE X PADDLE T
     O VARY ROT, AND           Y PADDLE TO V
     ARY SCALE.": GOSUB 975
1760  HOME : PRINT  TAB( 5);"USE THE X GAME
     PADDLE TO CHOOSE YOURSHAPE NO.  PRESS T
     HE PADDLE'S BUTTON    WHEN FINISHED.": GOSUB
     140:SH = S1
1765  PRINT : PRINT TAB( 5);"INPUT THE HCOL
     OR USING THE Y PADDLE.PRESS ITS BUTTON
     WHEN FINISHED.": GOSUB 160:HC = S1
1770  HGR : HOME : VTAB 21: PRINT TAB( 5):"
     USE THE SAME PADDLES TO LOCATE THE POI
     NT WHERE THE SHAPE WILL BE DRAWN. PR
     ESS EITHER BUTTON WHEN FINISHED."s GOSUB
     100:XI = INT (X):YI - INT (Y)
1775  HOME : VTAB 21: PRINT TAB( 5);"USE PA
     DDLES TO VARY ROTATION (X) ANDSCALE (Y)
     .  PRESS EITHER BUTTON TO STOP.": VTAB
     23: PRINT "SHAPE #"SH SPC( 3)"HCOLOR="H
     C SPC( 3)"X="XI SPC( 3)"Y="YI: GOSUB 17
     4: RETURN
1800  FOR J = N - VS + 1 TO DD: N = N + 1: POKE
     N,0: NEXT J
1810 N = VS + 1:J = 256 * PEEK (MS) + PEEK
     (LS) + TS: FOR K = 1 TO DD - 1: POKE J,
      PEEK (N):J = J + 1:N = N + 1:s NEXT K: RETURN
3500  GOSUB 1000
3501  GOSUB 1060: REM ENTRY FOR ADDING TO E
     XISTING TABLE
3502  HOME : GOSUB 770: GOSUB 975: IF F2 THEN
      RETURN
3505  GOSUB 270: HOME : TEXT : PRINT RS" SHA
     PES MAY BE ADDED TO THE CURRENT": PRINT
     "TABLE WHICH CONTAINS ": PEEK (2048);"
     SHAPES.": GOSUB 975
3510  IF NOT RS THEN 3575
3515  HOME : PRINT TAB( 5);"DO YOU WISH TO
     DRAW A SHAPE": PRINT "Y/N?";: SET Z$: IF
     Z$ < > "Y" AND Z$ < > "N" THEN 3515
3520  IF Z$ = "N" THEN 3575
3525  GOSUB 1200
3530  GOSUB 1350
3535  GOSUB 1500
3540  GOTO 3502
3575  RETURN
3650  GOSUB 8000: ONERR GOTO 20000
3660  PRINT : PRINT D$"BLOAD"NA$",A"TS: GOSUB
     270: GOSUB 212: GOSUB 203: GOSUB 700: POKE
     216,0: RETURN
3670  HOME : PRINT TAB( 5);"YOUR FILE NAME
     LENGTH IS ZERO.  DO  YOU STILL WISH TO
     BLOAD A SHAPE TABLE   FROM DISKETTE (Y/
     N)?": GET Z$: IF Z$ < > "Y" AND Z$ < >
     "N" THEN 3670
3680  IF Z$ = "N" THEN RETURN
3690  IF Z$ = "Y" THEN 3650
4000  HOME : IF PEEK (TS) > 0 THEN 4100
4010  PRINT TAB( 5);"PRESS THE NUMBER OF YO
     UR CHOICE.": PRINT : PRINT "1) DRAW BHA
     PES/CONSTRUCT A SHAPE TABLE.": PRINT "2
     ) BLOAD A SHAPE TABLE THAT HAS BEEN
        CONSTRUCTED WITH THIS ROUTINE.": PRINT
     "3) QUIT."
4014  GET Z$: IF VAL (Z$) < 1 OR VAL (Z$) >
     3 THEN HOME : GOTO 4010
4016  IF Z$ = "3" THEN 30000
4020  ON VAL (Z$) BOGUS 3500,3650
4030  GOTO 4000
4100  HOME : PRINT TAB( 5);"PRESS THE NUMBE
     R OF YOUR CHOICE.": PRINT
4105  PRINT : PRINT "1) DISPLAY SHAPES IN CU
     RRENT TABLE.": PRINT : PRINT "2) ADD SH
     APES TO CURRENT TABLE.": PRINT : PRINT
     "3) CHANGE A SHAPE IN CURRENT TABLE."
4110  PRINT : PRINT "4) BSAVE CURRENT TABLE
     TO DISKETTE.": PRINT : PRINT "5) DELETE
      TABLE CURRENTLY IN MEMORY.": PRINT : PRINT
     "6) QUIT.": PRINT
4120  GET Z$: IF VAL (Z$) < 1 OR VAL (Z$) >
     6 THEN 4100
4130  IF Z$ = "6" THEN 30000
4150  HOME : ON VAL (Z$) GOSUB 5200,5400,56
     00,5800,6000
4160  GOTO 4000
5200  TEXT : HOME : IF PEEK (TS) = 0 THEN PRINT
     "THERE ARE NO SHAPES IN TABLE.": GOSUB
     975: RETURN
5205  GOSUB 265: PRINT TAB( 5);"PRESS THE N
     UMBER OF YOUR CHOICE.": PRINT : PRINT "
     1) VIEW ALL SHAPES.": PRINT : PRINT "2)
      VIEW ONLY ONE SHAPE.": PRINT : PRINT "
     3) RETURN TO MAIN MENU."
5210  GET Z$: IF VAL (Z$) < 1 OR VAL (Z$) >
     3 THEN 5200
5215  IF Z$ = "3" THEN RETURN
5220  ON VAL (Z$) GOSUB 1700,17501 GOTO 520
     0
5400 GOSUB 3501: RETURN
5600  TEXT : HOME : IF PEEK (TS) = 0 THEN PRINT
      TAB( 5);"THERE IS NO TABLE CURRENTLY I
     N      MEMORY.": GOSUB 975: RETURN
5610  PRINT TAB( 5):"THERE ARE " PEEK (2048
     )" SHAPES IN TABLE.": INPUT "   ENTER
     THE NUMBER OF THE SHAPE YOU    WISH TO C
     HANGE, OR A ! TO RETURN TO THE MAIN MEN
     U";SH$: IF SH$ = "!" THEN F5 - 0: RETURN

5620 SH = VAL (SH$): IF SH < 1 OR SH > PEEK
     (TS) THEN 5600
5630 F5 = 1: GOSUB 210: GDSUB 1200: GOSUB 13
     50: GOSUB 1500
5640  IF Z$ = "Y" THEN GOSUB 1800
5660  GOTO 5600
5800  IF PEEK (TS) = 0 THEN PRINT "THERE A
     RE NO SHAPES IN TABLE.": GOSUB 975: RETURN

5805  PRINT "IF YOU WISH TO SAVE THIS TABLE
     ON A     DIFFERENT DISKETTE, PUT IT IN
     THE DRIVE AT THIS TIME.": PRINT : PRINT
     "PUT THE UTILITY DISKETTE BACK INTO THE
       DRIVE AFTER THE DISK DRIVE'S RED LIGH
     T GOES OFF.": GOSUB 975: GOSUB 8000: PRINT

5810  PRINT : PRINT D$"BSAVE"NA$",A"TS",L"PA
      - TS: RETURN
5820  HOME : PRINT TAB( 5);"YOUR FILE NAME
     LENGTH IS ZERO. DO YOU STILL WISH TO
     SAVE THE SHAPE TABLE THAT IS CURRENTLY
      IN MEMORY (Y/N)?";: GET Z$: IF Z$ < >
     "Y" AND Z$ < > "N" THEN 5820
5830  IF Z$ = "N" THEN RETURN
5840  GOTO 5800
6000  HOME : PRINT TAB( 5);"TYPE THE WORD "
     ;: FLASH : PRINT "DELETE";: NORMAL : PRINT
     " TO DESTROY": PRINT "THE SHAPE TABLE T
     HAT IS CURRENTLY IN    MEMORY. TYPE ";
     : FLASH : PRINT "SAVE"
6002  NORMAL : PRINT " IF YOU DO NOT WISH TO
     DESTROY THE SHAPE TABLE THAT CURRENTLY
      IS IN MEMORY."
6005  PRINT : INPUT "     PRESS THE RETURN K
     EY AFTER YOUR    CHOSEN ENTRY -> ";Z$
6010  IF Z$ < > "DELETE" AND Z* < > "SAVE"
      THEN 6000
6020  IF Z$ = "DELETE" THEN RUN
6030  RETURN
8000  HOME : PRINT TAB( 5);"ENTER THE NAME
     OF THE TABLE, THEN    PRESS RETURN. THE
      TOTAL LENGTH CAN NOT EXCEED 30 CHARACT
     ERG, AND THE FIRST     CHARACTER MUST B
     E A LETTER."
8005 NA$ = "":X = 2:Y = 6: HTAB X: VTAB Y
8010   GET Z$
8020  IF LEN (NA*) = 0 AND ASC (Z$) < 65 OR
      LEN (NA$) = 0 AND ASC (Z$) > 90 THEN
      VTAB 10: HTAB 1: PRINT "THE FIRST CHAR
     ACTER MUST BE A LETTER.";: FOR I = 1 TO
     1500: NEXT I: HTAB 1: CALL - 866: HTAB
     X: VTAB Y: GOTO 8010
8030  IF Z$ = "," THEN VTAB 10: HTAB 1: PRINT
     "DO NOT USE ANY COMMAS";: FOR I = 1 TO
     1500: NEXT I: HTAB 1: CALL - 868: HTAB
     X: VTAB Y: GOTO 8010
8040  IF ASC (Z$) = 8 AND LEN (NA$) > 1 THEN
     X = X - 1: HTAB X: CALL - 868:NA$ = LEFT$
     (NA$, LEN (NA$) - 1): GOTO 8010
8050  IF ASC (Z$) = 8 AND LEN (NA$) = 1 THEN
     X = X - 1: HTAB X: CALL - 868:NA$ = ""
     : GOTO 8010
8055  IF  ASC (Z$) = 13 OR  LEN (NA$) > 29 THEN
      RETURN
8060  PRINT Z$;:NA$ = NA$ + Z$:X = X + 1: HTAB
     X: GOTO 8010
8070  IF ASC (Z$) = 13 THEN RETURN
20000 ER = PEEK (222):LN = PEEK (218) + PEEK
     (219) * 256
20010  IF LN = 3660 THEN 21000: REM  FILE N
     OT FOUND ERROR WHEN ATTEMPTING TO LOAD
     A SHAPE TABLE
20020  IF ER = 11 AND LN = 5810 THEN PRINT
     "FIRST CHARACTER IN FILE NAME MUST BE
       A LETTER, AND NO COMMAS MAY APPEAR IN
        THE NAME. PRESS ANY KEY TO CONTINUE
     .": GET Z$:Z$ = "4": GOTO 4150
20050  STOP
21000  POKE 34,71 HOME : PRINT TAB( 5);"YOU
     R INPUT FILE NAME DOES NOT EXIST ON DIS
     KETTE. DO YOU WISH TO SEE A       CATAL
     OS LISTING OF THE DISKETTE THAT IS CURR
     ENTRY IN THE DRIVE (Y/N)?": POKE 34,0
21010  GET Z$: IF Z$ < > "Y" AND Z$ < > "N
     " THEN 21000
21020  IF Z$ = "N" THEN GOTO 21050
21030  PRINT : PRINT D$"CATALOG"
21040  PRINT : PRINT TAB( 5);"PRESS ANY LET
     TER TO CONTINUE.": GET Z$
21050  POKE 216,0: GOTO 4000
30000  END