                     CREATING AND USING
                   S H A P E  T A B L E S
                   ----------------------

     One of the things that makes Coleco's description of
shape tables confusing is the shape they use as an example.
The first step in creating a shape table is to draw a shape
on graph paper using arrows to show the direction to draw 
the particular shape.  One very important thing to remember
is that when a shape is drawn, a POINT IS PLOTTED FIRST, 
THEN(!!!) THE MOVE TAKES PLACE.  We will start with a shape
on simulated graph paper(and simulated arrows) and create a
shape table.  Here is the definition of the arrows used in 
this article:
     ^ =move up with no plot first
     > =move right with no plot first
     \/ =move down w.n.p.f.
     < =move left w.n.p.f.

     ^
     0 = Plot a point, then move up

     0> =Plot a point, then move right

     0 =Plot a point, then move down
     \/

     <0 =Plot a point, then move left

     Unless you keep in mind that the point is plotted first
and then the pen is moved, your shape will not end up as you
intended it to.  Here is our example shape; I will show it
twice. Once without the arrows and once in arrow form.

          -----------------
          | x | x | x |   |
          -----------------
          | x |   | x | x |
          -----------------
          | x |   | x | x |
          -----------------
          | x | x | x |   |
          -----------------

DRAWING    -------------------------
starts ->  |  0> |  0> |  0  |     |
here.      ---^-----------\/--------
           |  0  |     |  0> |  0  |
           ---^-----------------\/--
           |  0  |     |  0  | <0  |
           ---^-----------\/--------
           |  0  | <0  | <0  |     |
           -------------------------
     It doesn't matter where you start drawing your shape,
as long as you pick a place to start and then trace a path
around your shape so that you end up back where you started
or at least pointing to an already plotted point.  NOTE: 
If you will want to rotate your shape, remember that it will
rotate on the point that you started from.  In other words,
when you draw this shape from SmartBasic (ie. 1110 DRAW 1 at
x,y); 'x' and 'y' will be the axis for the rotation. 'x,y'  
will be that first dot of your shape where the drawing was
started from(in our example, this was the upper left corner)
and that point wil remain stationary as the rest of the 
shape rotates around it or is drawn at a different angle
(rotation) from that point.  If you don't understand this,
don't worry now. You will see what I mean later.

     The next step is to "unwrap" the shape into straight 
line of vectors. Start unwrappng your shape from the point
that you started drawing it and follow the arrows around the
shape but always look at the shape from the same angle and
record the vector exactly as it looks from that angle. The
"unwrap" for our example appears below.

0> 0> 0  0> 0  <0 0  <0 <0 ^ ^ ^
      \/    \/    \/       0 0 0

     Next, you "cut" the "unwrapped" line into pairs of
vectors like this:

| 0> 0> | 0  0> | 0  <0 | 0  <0 | <0 ^ | ^ ^ |
|       | \/    | \/    | \/    |    0 | 0 0 |

     Each vector has a corresponding code found in a table
on page C-18 in the SmartBasic manual.  Each pair of vectors
must be translated into an eight bit byte. Since each vector
code is composed of only three bits, two zeros are added to
the beginning of the byte for each vector pair.  NOTE:  It
is possible to use this third two bit position to represent
a MOVE ONLY of either right, down, or left. Doing this would
create a vector triplet byte instead of a vector pair byte.

The first vector pair becomes: 00101101. This is how we go
about getting that result:

| 0> 0> | = 00(unused two bit position) + 101(code of second
            vector in pair) + 101(code for first vector in
            pair). -or- 00 + 101 + 101 = 00101101.

The second vector pair becomes: 00101110.

| 0  0> | = 00(unused two bit position) + 101(code of second
| \/    |   vector in pair) + 110(code for first vector in
            pair). -or- 00 + 101 + 110 = 00101110.

     Doing this to all the vector pairs in our "unwrapped"
line produces the following list of bytes.  Make sure that
you came up with these results before you continue .  If you
didn't, then go back and reread the instructions until you
are sure that you understand everything up to this point.

         Byte list for "unwrapped" line.
         -------------------------------
  00101101   - first vector pair
  00101110   - second "      "  
  00111110         .
  00111110         .
  00100111         .
  00100100   - sixth & last vector pair

     Now you have a choice to make.  You can either convert
each byte directly to decimal, or first convert it to hex 
and then to decimal. Either way, you must convert each 
binary byte to its decimal equivalent.  you can easily write
a short program to convert binary numbers to decimal. Just 
in case you don't understand binary numbers, here is a con-
version chart:

|128's|64's|32's|16's|8's|4's|2's|units|
----------------------------------------
| 0   | 0  | 1  | 0  | 1 | 1 | 0 |  1  |
               -or-
| 0   + 0  + 32 + 0  + 8 + 4 + 0 +  1  = 45

     Or via hex; using chart on C-19
00101101 
  to
0010  1101
  to
 2     D
  to
2D
THEN:

| 4096's | 256's | 16's | units|
--------------------------------
|   0    |   0   |  2   |  D   |
            -or-
|   0    +   0   +  32  + 13   = 45

     Now you should have a list of decimal numbers. Each one
corresponding to one of the vector pairs. This is the shape
data. Add a zero to the end of the list. This zero tells 
ADAM that this is the end of this shape. Your list should 
now look like this:

45
46
62
62
39
36
0

     Before you can use this data, there are a few things
that you must do. The first is to create an index for the
shape table. It is possible to have up to 255 separate 
shapes in any one shape table. The number of bytes in the
index increases every time a shape is added. Also the 
pointers change as shapes are added because of the length
change in the index. The index is set up in the following
manner:
     nnn- number of shapes(up to 255)
       0- BASE POINT(always zero)(shapes indexed from here)
     Ls1- least sig. byte of pointer to first shape.
     Ms1- Most sig. byte of pointer to first shape. 
     Ls2- LSB of pointer to second shape.
     Ms2- MSB of pointer to second shape.
     Ls3- LSB of pointer to third shape.
     Ms3- MSB of pointer to third shape.
     .
     .
     .
     up to 255 shapes maximum.
     (the minimum is one shape).

The index for our example shape would be as follows:

01 - only one shape
00 - Base point
04 - LSB of offset (from BP) to beginning of first shape.
00 - MSB of offset (from BP) to beginning of first shape.

     The completed shape table would be:

     01  - # of shapes
     00  - BP - off.=1
off /04       - off.=2
set \00       - off.=3
     45  ------ off.=4
     46
     62
     62
     39
     36
     00

     If we had more than one shape, our index would reflect
this increase. We will use the same shape twice; making it
both shape #1 and shape #2 in the following example.

     02  - # of shapes
     00  - BP - off.=1
off /06  -LSB - off.=2
set \00  -MSB - off.=3
off /13  -LSB - off.=4
set \00  -MSB - off.=5
     45  ------ off.=6 - begin of shape #1
     46       - off.=7
     62       - off.=8
     62       - off.=9
     39       - off.=10
     36       - off.=11
     00       - off.=12
     45  ------ off.=13 - begin of shape #2
     46       - off.=14
     62       - off.=15
     62       - off.=16
     39       - off.=17
     36       - off.=18
     00       - off.=19 - end of shape#2

NOTE : a shape #3 would not be at offset=20!!! This is due
to the fact that to add a third shape would require two 
extra locations in the index. ALSO the pointers to shapes
#1 and #2 would also change to reflect the increased size of
the index.

     Our shape table is now created!!!! However, before we
can use it there are a few things we must do. We must load
the shape table into some protected memory, tell Smartbasic
where our table is, then set the ROTation, set the HCOLOR,
and set the SCALE. 
     There two ways to load the shape table. One is to write
a program to load the table into memory; then BSAVE it onto
our disk or data pack so it can later be BLOADed by the 
program we wish to use it in; OR we can write a subroutine
in our main program to load the shape table.  I prefer to 
create and BSAVE my shape tables. There are advantages to
both ways. Loading the shape table from the main program 
would be your choice if you planned to upload the program
to a BBS and couldn't upload a binary file (like with 
ADAMlink II). A drawback to this method is that in addition
to the memory lost by raising LOMEM or lowering HIMEM (to
protect the table in memory), you would also increase the 
overall length of your program (due to the loader subroutine
and the DATA statements required). If, however, your program
was already very long (over 20K), or you wanted to use the
same shape table in more than one program, BSAVEing it would
probably be your best bet.  I will show you both ways and
then you can decide which fits your needs.

     LOADING OUR EXAMPLE TABLE FROM WITHIN THE MAIN PROG.
     ----------------------------------------------------

10 LOMEM : 27427              10 HIMEM : 54140
20 GOSUB 10000                20 GOSUB 10000
.                             .
.       Your                  .       Your
.     Program                 .     Program
.                             .
10000 FOR off=0 to 19         10000 FOR off=0 to 19
10010 READ val                10010 READ val
10020 POKE 27407+off,val      10020 POKE 54141+off,val
10030 NEXT off                10030 NEXT off
10040 REM Tell Smart Basic where table is.
10050 RETURN                  10050 RETURN
11000 DATA 2,0,6,0,13,0       11000 DATA 2,0,6,0,13,0
11010 DATA 45,46,62,62,39     11010 DATA 45,46,62,62,39
11020 DATA 36,0,45,46,62      11020 DATA 36,0,45,46,62
11030 DATA 62,39,36,0         11030 DATA 62,39,36,0

     PROG TO CREATE AND SAVE TABLE
     -----------------------------
Lines 10, 20, and 10000 thru 11030 would be the same.
However, add these lines:
30 print"When prog stops, type : BSAVE MYTBL,a27407,l20
  - or-
30 print"When prog stops, type : BSAVE MYTBL,a54001,l20
40 END

     The next question I can see rising is where did I get
the LOMEM and HIMEM values. Simple. Our example shape table
has 20 values. SmartBasic uses memory locations 0 - 27406. 
LOMEM (the lowest memory location available to be used by
our programs and variables) is set by SmartBasic at 27407.
Since our example table is 20 values long, we must protect 
20 memory locations. Therefore : 27407 + 20 = 27427. If you
would rather use HIMEM (the highest mem. loc. available to
the user) you must protect at least 20 locations beneath
the allowable POKEing limit set by SmartBasic which is
54160. Therefore 54160 - 20 =54140. Note that when POKEing,
I started at 54141. This is because 54141 is the first PRO-
TECTED memory location. 54140 can be used by our program. I
personally like to poke my shape tables below LOMEM rather
than above HIMEM. This is because it seems that although
SmartBasic doesn't allow POKEing above 54160, It does let 
a program use some space above it.  

     The last thing you must do before you can use a shape
table is let SmartBasic know where the table resides. This
is done with two POKES. 16766 must be poked with the LSB of
the starting address of the table and 16767 must be poked
with the MSB of the starting address of the table. To deter-
mine the values to be poked, do the following:
     Convert the starting address to a 16 bit binary number.
     Split the 16 bit byte into two eight bit bytes.
     Convert the low eight bits into decimal (LSB).
     Convert the high eight bits into decimal as if they
          were eight low bits (MSB).
For a starting address of 27407:

32768|16384|8192|4096|2048|1024|512|256|128|64|32|16|8|4|2|U
------------------------------------------------------------
  0  |  1  | 1  | 0  | 1  | 0  | 1 | 1 | 0 | 0| 0| 0|1|1|1|1

this yeilds 0110101100001111
Split down  01101011 (MSB)
            00001111 (LSB)
then:
|128 |64 | 32| 16| 8| 4| 2| units
---------------------------------
| 0  | 1 | 1 | 0 | 1| 0| 1| 1     = MSB =107
| 0  | 0 | 0 | 0 | 1| 1| 1| 1     = LSB =15

So our pokes are :  POKE 16766,15
                    POKE 16767,107
We can then replace line 10040 with:
     10040 POKE 16766,15 : POKE 16767,107
 For 54141 it would be:
     10040 POKE 16766,125 : POKE 16767,211
Finally we are ready to use our shape table!!!!!
Here are the programs needed to use our shape table. I've
wrote one in case you want to use a table BSAVEd, and one
in case you want to use a table loaded by the main program.

Using a BLOADed shape table:
----------------------------
10 LOMEM : 27427
20 d$=chr$(4)
30 HTAB 1 : print d$;"BLOAD MYTBL,A27407"
40 POKE 16766,15 : POKE 16767,107
50 HGR
60 c=2 : s=1 : r=0 : x=100 : y=100
70 HCOLOR=c
80 SCALE=s
90 ROT=r
100 IF PDL(7)=1 THEN GOSUB 1000
110 IF PDL(9)=1 THEN GOSUB 2000
120 IF PDL(13)=0 THEN GOSUB 3000
130 DRAW 1 AT x,y : DRAW 2 AT x+30,y+30
140 GOSUB 4000
150 XDRAW 1 AT x,y : XDRAW 2 AT x+30,y+30
160 m=PDL(5)
170 IF m=1 then y=y-1
180 IF m=2 then x=x+1
190 IF m=4 then y=y+1
200 IF m=8 then x=x-1
210 IF x>255 then x=255
220 IF x<0 then x=0
230 IF y>159 then y=159
240 IF y<0 then y=0
250 GOTO 70
1000 c=c+1
1010 IF c>15 then c=0
1020 RETURN
2000 s=s+1
2010 IF s>255 then s=1
2020 RETURN
3000 r=r+1
3010 IF r>63 then r=0
3020 RETURN
4000 FOR t=1 to 200 : NEXT t : RETURN 

Using a shape table loaded with the Main prog.:
-----------------------------------------------
Add lines 50 to 4000 from above program to one of the two
programs listed before in the spot where it says "Your
Program".

     The above program will continually draw and erase both
of the shapes in the table. By moving the Joystick, you
can move both shapes around the screen. Pressing the left
trigger changes the color they are drawn in. Pressing the
right trigger increases the scale.  Pressing the # 0 on the
Joystick changes the rotation. 

     I hope I have managed to teach you how to create and
use shape tables in SmartBasic. If you have trouble under-
standing anything in this Article, First reread the article,
then if you still don't get it, don't hesitate to call me 
(voice) at 1-201-956-9482.  Watch for my monthly SmartBasic
Programming column in the ADAM UNDERGROUND newsletter from
the Coleco's Adam Users Group (CAUG). Enjoy!
      GREGG NOBLETT
     (70317,3207)
