Classic Computer Magazine Archive ANTIC VOL. 4, NO. 12 / APRIL 1986

CONTROL GEM WITH ST BASIC

Part 1: VDI calls

by JAMES LUCZAK
Article by JACK POWELL and PATRICK BASS

ST BASIC has the potential to be a pretty powerful language-if you can get to it. Right now, it's buried under several windows and a particularly bad screen editor. But one very handy thing ST BASIC provides-to all programmers-is a fast way to test GEM's VDI and AES routines.
   Unfortunately, Atari's ST BASIC Sourcebook only mentions the GEM routines in passing and gives just a few examples of how to use them. There's a good reason for this. The entire VDI and AES system consists of over 200 calls. Pretty daunting. But we all have to start someplace, so let's get at it.
   In this issue, we will show you most of the GEM VDI calls and how to access them from BASIC. Next month, we'll finish up any leftover VDI material. Although we will be displaying our examples for ST BASIC, with a little effort, programmers of any language should be able to use the information.
   But before we get our hands dirty, lets take a look at what we're playing with.

GEM IN A NUTSHELL
We refer you to the Antic January 1986 ST Section, TOS Roadmap for greater details. Briefly, GEM-which stands for Graphics Environment Manager-is a software interface between the ST operating system and the user. GEM, in turn, is made up of two parts: VDI and AES.
   AES, which is mnemonic for Application Environment Services, is made up of VDI elements. And VDI, meaning Virtual Device Interface, consists of some even smaller routines. But for our current purposes, we will consider VDI to be the smallest building blocks in GEM.
   When we speak of building blocks, we are really talking about machine language routines in the ST operating system which may be pointed to for accomplishing certain tasks. We might, for example, go to a VDI routine to draw one line in a desktop window. But we would go to an AES routine to draw the entire window.

WHY GEM?
When Digital Research, Inc. (DRI) sat down to write GEM, they decided to write it so that any applications program written according to the GEM guidelines would run on any other computer that also had GEM installed.
   Not an easy task. The way DRI solved the problem was to set GEM up as a "virtual" computer. They decided what the perfect computer-regardless of manufacture-should perform like. They choose the perfect resolution, how many colors could be displayed, what devices could be driven, how information is exchanged and so forth. The "software" computer they designed is GEM.
   For each version of GEM-such as the 520ST or IBM PC-DRI programmed GEM to translate the commands for the virtual computer into commands that came as close as possible to the machine they had GEM running on. The result is that the same set of instructions should perform the same job on either the IBM PC or the 520ST
   So it turns out that when you think you're programming your 520ST using GEM calls, you're really programming some super software computer deep inside the 520ST, and GEM is translating the commands from GEM to 520ST specific.

VIRTUALLY THERE
As mentioned, GEM consists mostly of machine language routines-or subroutines. These routines are accessed from higher languages in a way very similar to machine language routines in BASIC. This implies we will need to pass information to GEM and get information back.
   DRI has classified the information into five different groups: Contrl, Intin, Intout, Ptsin, and Ptsout. All five of these groups are arrays which hold integer (16-bit) values. Each array is much like a blackboard. The user writes values-or instructions-to GEM, which then acts upon them. The blackboard also provides a place for GEM to reply.
   Intin and Intout (Integers In, Integers Out) are arrays for input and output parameter passing. Ptsin and Ptsout (Points In, Points Out) are for passing and receiving point coordinates. Contrl provides a place for passing and receiving Control values, such as opcodes and identification numbers.
   Each VDI and AES routine contains an identification number, or opcode. When you wish to use a particular routine, it must be identified by its opcode number which is always placed in the zeroth element of the Contrl array.
   Beyond that, the elements of the input arrays will require certain information, depending upon that routine's function. And certain output array elements may or may not return values which also may or may not be used by the programmer.
   For practical purposes, what you as a programmer need to know is the name of the routine, the identifying op-code (taken care of by link files in most C languages), what the routine does, what input parameters it expects and where to put them, plus what output parameters are returned and whether to use them.

BASIC AND C
Were going to concentrate on BASIC here, but we'll throw in some details for you C programmers. Although there are currently no published sources of information on VDI and AES (outside of the Atari Developer's Kit), we fully expect there will be some available by the time this article appears in print.
   To see how the arrays are used, let's follow, in BASIC, a VDI routine which is called v_pline in C. v_pline, which stands for VDI Polyline, has an identifying opcode of 6 and is used to draw one or more lines between points.
   We're going to draw a diagonal line from XY coordinates 0,0 to XY coordinates 100,100.
   In BASIC v_pline takes the form:

BASIC code              What it does
10 poke contrl,6        vpline OPCODE number.
20 poke
contrl+2,num            num is the number of
                        points to plot.
30 poke contrl+6,0      should always be zero.
40 poke ptsin,0         X-coordinate of first point.
50 poke ptsin+2,0       Y-coordinate of first point.
60 poke ptsin+4,100     X-coordinate of second point.
70 poke ptsin+6,100     Y-coordinate of second point.
80 vdisys(1)            Transfers control to GEM VDI

   BASIC thinks in 8-bit bytes, and the GEM arrays are set up as 16-bit integers. Therefore, when POKEing VDI instructions in BASIC, we need to double each register number to point to the proper location to poke.
   For contrast, let's look at a C listing for the same call. In C, you must also open a workstation before you can use any of the GEM system calls. We're not showing this here, but you will see it in any C listing in Antic. Look for the v_opnvwk() call.
   In C, we put our instructions in the elements of an integer array, then place the entire array within the parentheses of the VDI call. Since the opcode number for the call is taken care of in a separately linked file, we used a pre-established label to identify the call. Alcyon C and its DRI developers' documentation have chosen the name v_pline in this case (which stands for VDI Polyline). Antic hopes these labels will remain standard, though some language developers may (shudder) choose to rename them.
   Our v_pline call in C is:
int     points[4];      declare our points array.
  points[0]=0;
  points[1]=0;
  points[2]=100;
  points[3]=100;
  v_pline( handle, 2, points);

THE VDI CALLS
We have arranged the VDI functions in four groups- Polymarkers, Polylines, Text, and Graphics.
   Polymarkers are routines which plot one or more single points of a chosen shape to the screen. Polyline routines draw one or more lines to the screen. v_pline() is a polyline. The text routines manipulate text in a variety of ways. Graphics is a catch-all category of routines not covered in the first three categories.
   Each of the functions, as listed, contains the name of the routine, the necessary BASIC code to set up the parameters, and a description of what the routine does. Many of the functions also have a list of attributes that will modify the action of the routine. You may also see notes referring you to related VDI calls.
   Let's take a look at our familiar v_pline call. You'll find it in the polylines subgroup under the title "Polyline." The BASIC pokes are in the left column and their description is in the right. C programmers can identify the routine from its opcode number in Line 1.
   The description gives you some idea of what polyline will do. The list of attributes tells you that you may adjust, among other things, the polyline's color, the type of line it is drawn with, that line's width, and so on. Looking elsewhere in the polyline section, you will find VDI calls-such as "Set Polyline Line Type"-that will adjust these attributes. On the bottom of the polyline description is a note pointing you to Extended Inquire" for related information.

THE DEMONSTRATION
Listing 1 is an ST BASIC program that demonstrates some VDI routines. Type it in and SAVE a copy before you RUN it. (No, we don't have a TYPO II for ST BASIC yet.)
   We are going to draw a rounded and filled rectangle, then draw a trapezoid polyline within it, using a thickened line. Next, we will randomly place 100 multi-colored and shaped polymarkers on the screen. Finally, we alter the text output to skewed, underlined and green, and print a message to the screen.
   In lines 1060 to 1180 we initialize some variables- mostly setting them up as reminders of their functions. But, in line 1060, the pxy array must be dimensioned since more than 10 array elements are going to be used in our program.
   We briefly check for resolution in lines 1210 to 1240, then on to the main portion of our program.
   Without going into line-by-line detail, you can see that we've placed the various VDI calls in labeled subroutines in the last two-thirds of the listing. (Our labels are the same as those used by Alcyon C, with the exception that there are no underline characters.) You might try collecting all your VDI calls in subroutine files which later can be used in any program you write.
   The rounded rectangle is created in lines 1330 to 1380. Since we are going to do a filled rectangle, we first choose the fill color, then choose the fill interior style, and finally the index into that fill style. You can find the fill pattern styles and indexes in your ST BASIC Sourcebook.
   Having set up our rectangle, we work out the proper X,Y coordinates for its upper-left and lower-right corners and then go off and actually draw the box.
   In lines 1420 to 1550, we use the polyline routine to draw an odd-shaped box with thick, red lines. (Those with monochrome monitors will find that any color value that is not zero will be black.) Notice that although there are only four corners to our polyline, we have five vertices (or X,Y points) because we must include both the beginning and ending points in our array.
   Lines 1580 to 1770 place various polymarkers in random places on the screen. Then, in lines 1810 to 1880, we print skewed, underlined, green text on the screen. Note that we go to subroutine VSWRMODE to adjust the write mode of the text to transparent, so it won't look blocky if printed over a polymarker.
   At the end of the program, we set our text effects back to normal, close our window and leave. It's always good programming practice to leave your work area the way you found it.

Listing 1  VDI SHOW

POLYMARKERS

POLYMARKER
BASIC CODE             DESCRIPTION

1 poke contrl,7        OPCODE
2 poke contrl+2,num    NUM=Number of markers
3 poke contrl+6,0
4 poke ptsin,x         X=Coordinate of first marker
5 poke ptsin+2,y       Y=Coordinate of first marker
6 vdisys(1)

A POLYMARKER plots a point expressed by it's X and Y coordinates. More than one point can be plotted at the same
time. Enter the number of points to be plotted in LINE 2 (num), then give the X and Y coordinates for each point as in
LINES 4 and 5. Increase the offset for PTSIN by 2 for each additional X and Y coordinate pair. For example, to plot 2 separate points, follow the above code. In LINE 2 give the variable num a value of 2 (for 2 points). Add LINES 6 and 7 as follows. LINE 6 poke ptsin+4,x1 LINE 7 poke ptsin+6,y1.
ATTRIBUTES:
Color
Scale
Type
Writing Mode
NOTE: See EXTENDED INQUIRE for maximum number of POLYMARKERS.

SET POLYMARKER COLOR INDEX
BASIC CODE             DESCRIPTION
1 poke contrl,20       OPCODE
2 poke contrl+2,0
3 poke contrl+6,1
4 poke intin,x         X=Color Index (See COLOR INDEX)
5 vdisys(1)

SET POLYMARKER HEIGHT
BASIC CODE             DESCRIPTION
1 poke contrl,19       OPCODE
2 poke contrl+2,1
3 poke contrl+6,0
4 poke ptsin,0
5 poke ptsin+2,y       Y=Height in vertical units
                       1-199 for LOW & MED 1-399 for HIGH
6 vdisys(1)
NOTE: You cannot set the HEIGHT of POLYMARKER TYPE 1 (See set polymarker type)

SET POLYMARKER TYPE
BASIC CODE             DESCRIPTION
1 poke contrl,18       OPCODE
2 poke contrl+2,0
3 poke contrl+6,1
4 poke intin,x         X=Polymarker type
                       1= Dot
                       2=Plus
                       3=Asterisk
                       4=Square
                       5=Diagonal Cross
                       6=Diamond
5 vdisys(1)
NOTE: If the marker type is out of range TYPE 3 is automatically selected.

INQUIRE CURRENT POLYMARKER ATTRIBUTES
BASIC CODE             DESCRIPTION
 1 poke contrl,36       OPCODE
 2 poke contrl+2,0
 3 poke contrl±6,0
 4 vdisys(1)
 5 a=peek(intout)      Polymarker Type
 6 b=rpeek(intout+2)   Polymarker Color Index
 7 c=peek(intout+4)    Writing Mode
 8 d=peek(ptsout)      Polymarker Width
 9 e=peek(ptsout+2)    Polymarker Height
10 vdisys(1)
NOTE: You need only PEEK at the attributes that are of interest to you.

POLYLINES

POLYLINE
BASIC CODE             DESCRIPTION
1 poke contrl,6        OPCODE
2 poke contrl+2,num    NUM=Number of X & Y pairs in the polyline.
3 poke contrl+6,0
4 poke ptsin,x         X=Coordinate of first point in polyline.
5 poke ptsin+2,y       Y=Coordinate of first point in polyline
6 poke ptsin+4,xl      X1=Coordinate of second point in polyline.
7 poke ptsin+6,yl      Y1=Coordinate of second point in polyline.
8 vdisys(1)
The POLYLINE function draws a line from one point expressed by it's X and Y coordinates to another point expressed by it's X and Y coordinates. The variable num in LINE 2 must have a miminum value of 2. You can draw more than one line by giving the appropriate X and Y coordinate pairs,

ATTRIBUTES:
Color
Line Type
Line Width
End Style
Writing Mode
NOTE: See EXTENDED INQUIRE for maximum number of POLYLINES.

SET POLYLINE COLOR INDEX
BASIC CODE             DESCRIPTION
1 poke contrl,17       OPCODE
2 poke contrl+2,0
3 poke contrl+6,1
4 poke intin,x         X=Color Index (See COLOR INDEX)
5 vdisys(1)

SET POLYLINE END STYLE
BASIC CODE             DESCRIPTION
1 poke contrl,108      OPCODE
2 poke contrl+2,0
3 poke contrl+6,2
4 poke intin,x         End style for begining point of polyline
5 poke intin+2,x       End style for ending point of polyline
                       0=Squared (DEFAULT)
                       1 =Arrow
                       2=Rounded
6 vdisys(1)

SET POLYLINE LINE TYPE
BASIC CODE             DESCRIPTION
1 poke contrl,15       OPCODE
2 poke contrl+2,0
3 poke contrl+6,1
4 poke intin,x
                       LINE STYLE
                       1 =Solid
                       2=Long Dash
                       3=Dot
                       4=Dash,Dot
                       5= Dash
                       6=Dash,Dot,Dot
                       7=User Defined
5 vdisys(1)

SET USER DEFINED LINE TYPE PATTERN
BASIC CODE             DECRIPTION
1 poke contrl.113      OPCODE
2 poke contrl±2,0
3 poke contrl+6,1
4 poke intin,x         Line style pattern word
5 vdisys(1)
The most significant Bit of the LINE STYLE PATTERN WORD is the first pixel in the line. For example a DASHED line style
pattern word:
BINARY : 1111111100000000
DECIMAL: 65280

SET POLYLINE LINE WIDTH
BASIC CODE             DESCRIPTION
1 poke contrl,16       OPCODE
2 poke contrl+2,1
3 poke contrl+6,0
4 poke ptsin,x         X=Line width in horizontal units
5 poke ptsin+2,0
6 vdisys(1)
NOTE: Line widths are expressed in ODD NUMBERS. Default is 1. (1 pixel wide).

INQUIRE CURRENT POLYLINE ATTRIBUTES
BASIC CODE             DESCRIPTION
 1 poke contrl,35      OPCODE
 2 poke contrl+2,0
 3 poke contrl+6,0
 4 vdisys(1)
 5 a=peek(intout)      Polyline Type
 6 b=peek(intout+2)    Polyline Color Index
 7 c=peek(intout+4)    Writing Mode
 8 d=peek(intout+6)    End style for begining point of polyline
 9 e=peek(intout+8)    End style for ending point of polyline
10 f=peek(ptsout)      Line Width
11 vdisys(1)
NOTE: You need only PEEK at the attributes that are of interest to you.


COLOR INDEX
COLOR                  PIXEL
INDEX    COLOR         VALUE
 0       White           0
 1       Black           15
 2       Red             1
 3       Green           2
 4       Blue            4
 5       Cyan            6
 6       Yellow          3
 7       Magenta         5
 8       Low White       7
 9       Grey            8
10       Light Red       9
11       Light Green    10
12       Light Blue     12
13       Light Cyan     14
14       Light Yellow   11
15       Light Magenta  13


(VDI listings will be continued next month.)