CONTROL GEM WITH ST BASIC
Part 1: VDI calls
by JAMES LUCZAKArticle 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
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.
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.)