CW CHAPTER 5
Jump to navigation
Jump to search
CHAPTER 5: INTRODUCING THE VDI
-------------------------------
[NOTE: Words enclosed in asterisks (i.e. *word*) should be
read as italicized text. This text file is copyright 1993 by
Clayton Walnum. All rights reserved.]
GEM (Graphics Environment Manager) is made up of many
libraries of functions, each of which handles certain
portions of the system's activities. These libraries are
grouped into two major units, called the AES (Applications
Environment Services) and the VDI (Virtual Device
Interface). The AES, which we've been using since the
beginning of the book, contains the functions we need to
handle windows, dialog boxes, menu bars, and event
processing. The VDI controls most of the ST's graphic
capabilities and provides some mouse and cursor control
functions, as well.
The VDI plays an important role in making your graphics
programs operate on many different devices. Unfortunately,
one of the crucial elements in the graphics interface, GDOS
(Graphics Device Operating System), is not built into the
current operating system. GDOS is the portion of the VDI
that links the graphics functions to the drivers needed to
assure that the graphics operate properly on all graphics
devices. GDOS also makes it possible to load different fonts
into your ST, using the standard VDI functions.
At this time, however, we're concerned only with one
device: the screen.
--The VDI functions--
The VDI provides a series of functions that let us quickly
draw many graphic shapes. This simplifies the development of
programs that rely heavily on graphics. If you programmed an
8-bit Atari (or still do), think of all the work involved in
drawing a circle. The VDI provides a function that will draw
any size circle we want--with a single call. There are also
functions for drawing ellipses, lines, rectangles, rounded
rectangles, arcs, pie slices and a number of other useful
graphics.
And it doesn't stop there. Each graphic function has a
group of related attributes that may be set before the
graphic is drawn, allowing various types of lines, fills and
colors.
--The Program--
This chapter's sample program shows how to set up your
program to use the VDI. It also includes a demonstration of
some of the VDI's graphics capabilities. Specifically, when
the program is run, you will see the different types of line
styles available through the VDI. To exit the program, press
your Return key.
--The VDI Arrays--
Calling VDI functions is a lot like calling AES functions.
In both cases, you must place appropriate values into
control and input arrays, and then call the function by
using a *trap #2* instruction. Look at the data section of
this chapter's sample program. There, you'll find the usual
AES parameter block (*apb*). Right below that, you'll see
something called *vpb*. Yep. That's a VDI parameter block.
Although these parameter blocks work the same way--that is,
they both tell the OS where to find the arrays it needs--
they contain different values. The VDI, for example, doesn't
use the *addr_in* or *addr_out* arrays. Let's look at the
*vpb* in detail.
The first value is the address of a control array. In
our *apb* we have a 0 in this location because we found it
easier to have different control arrays for each function,
and then plug the address of the appropriate array into the
*apb* when we needed it. But because the values in the VDI
control array vary from one function call to another, it's
clumsy to try to set them up ahead of time.
The *int_in* and *int_out* arrays are the same as those
in the *apb*. We can use the same arrays for either an AES
or VDI call. But the VDI *apb* has something a little
different, arrays called *pts_in* and *pts_out*. These
arrays usually contain coordinates for the VDI's drawing
functions. For example, the starting and ending screen
coordinates for a line would go into the *pts_in* array
before calling the function.
--Initializing the VDI--
When we use the VDI in our programs, we must set up
something called a virtual workstation. To do this, we do
the following:
1) Get a handle to the physical screen.
2) Open a virtual workstation.
3) Clear the virtual workstation.
Look at this chapter's program listing. After the usual
program initialization, which concludes with the call to
*appl_init*, we begin the VDI initialization. The first step
is performed by calling the AES function #77, *graf_handle*,
like this:
move.l #graf_handle,apb
jsr aes
move int_out,gr_handle
This returns the handle for the currently open device
(the screen) or workstation, as well as the size of the
system font. Because GEM is capable of having many programs
in memory at once, each requires some identification, to
keep commands for one program from corrupting another. This
is accomplished by assigning each program a handle. The
variable *gr_handle* in the above call is an integer value
that identifies the current workstation. After the call,
this value is found in the first element of the *int_out*
array.
The *graf_handle* call also returns some information
about the system font. The width of a character cell will be
in *int_out+2*, the cell height will be in *int_out+4*, the
width of a box that can enclose a character will be in
*int_out+6*, and the height of the box will be in
*int_out+8*. We won't be using any of this character
information now, but you should know where to find it when
you need it.
--The Virtual Workstation--
The *graf_handle* call returns the handle to the physical
workstation. What we really need for our program is a handle
to a virtual workstation. It's kind of tough to explain the
difference, but I'll give it a shot.
A particular device may have many virtual workstations,
but only one physical workstation. The physical workstation
is directly associated with the device itself, usually the
screen. You can think of a virtual workstation as a
"pretend" device. It has its own section of memory and keeps
its data and status completely separate from all other
virtual workstations. When you activate an application (such
as clicking on a desk accessory), it becomes bound to the
physical workstation. In a sense, it becomes the physical
workstation.
We get the handle for our virtual workstation with a
call to the VDI function #100, *v_opnvwk*, like this:
move #100,contrl
clr contrl+2
move #11,contrl+6
move gr_handle,contrl+12
movea.l #int_in,a5
move #9,d5
loop:
move #1,(a5)+
dbra d5,loop
move #2,int_in+20
jsr vdi
move contrl+12,vws_handle
This function expects the system attributes to be in
the *int_in* array. (In this example, we're loading the
values into *int_in* using a loop.) These attributes
determine default values for system attributes such as
default colors, fill patterns, and line styles. (For those
of you familiar with C, the *int_in* array in this call
serves the same function as C's *work_in* array.) In the
above example, we place a 1 in elements 1 through 10 of the
*int_in* array, and a 2 in the eleventh element of the
*int_in* array. This is the standard way to initialize these
attributes.
You should note the manner in which the control array
is used, since all VDI calls require similar parameters in
this array. The first element of the control array must
contain the opcode for the VDI function we wish to call.
*Contrl+2* must contain the number of point pairs that will
be found in the *pts_in* array, in this case, 0. *Contrl+6*
must contain the number of integer values that are in the
*int_in* array. In this function call, *int_in* will contain
11 values, so we place an 11 in *contrl+6*. Finally,
*contrl+12* must contain the device handle. In most VDI
calls, this value will be the handle to our virtual
workstation. However, because we don't yet have that handle,
we use the graphics handle that was returned by the call to
*graf_handle*.
After the call to *v_opnvwk*, our *int_out* and
*pts_out* arrays will contain much information about the
virtual device's current attributes, as follows:
control+4 -- 6 = # of point pairs in pts_out
control+8 -- 45 = # of integers in int_out
control+12 -- Device handle (0 if no device opened)
int_out, work_out[0] -- Maximum horizontal screen coord.
int_out+2, work_out[1] -- Maximum vertical screen coord.
int_out+4, work_out[2] -- Device coordinate units flag:
0 = Device can display a precisely scaled image.
1 = Device cannot display a precisely scaled image.
int_out+6, work_out[3] -- Width of a pixel in microns.
int_out+8, work_out[4] -- Height of a pixel in microns.
int_out+10, work_out[5] -- Number of font heights:
0 = continuous scaling.
int_out+12, work_out[6] -- Number of line types.
int_out+14, work_out[7] -- Number of line widths:
0 = Continuous scaling.
int_out+16, work_out[8] -- Number of marker styles.
int_out+18, work_out[9] -- Number of marker sizes:
0 = Continuous scaling.
int_out+20, work_out[10] -- Number of supported text fonts.
int_out+22, work_out[11] -- Number of pattern styles.
int_out+24, work_out[12] -- Number of hatch styles.
int_out+26, work_out[13] -- Number of available colors.
int_out+28, work_out[14] -- Number of generalized drawing
primitives.
int_out+30 to int_out+48
work_out[15] to work_out[24] -- Code numbers for available
generalized drawing primitives:
1 = filled bar.
2 = arc.
3 = pie slice.
4 = filled circle.
5 = filled ellipse.
6 = elliptical arc.
7 = elliptical pie slice.
8 = rounded rectangle.
9 = filled rounded rectangle.
10 = justified graphics text.
-1 = end of GDP list.
int_out+50 to int_out+68
work_out[25] to work_out[34] -- Code numbers for graphics
operations available to the GDPs:
0 = lines.
1 = markers.
2 = graphics text.
3 = fills.
4 = none.
int_out+70, work_out[35] -- Color flag:
0 = no colors available on device.
1 = colors available on device.
int_out+72, work_out[36] -- Text rotation flag:
0 = device cannot rotate text.
1 = device can rotate text.
int_out+74, work_out[37] -- Fill flag:
0 = device cannot fill areas.
1 = device can fill areas.
int_out+76, work_out[38] -- Cell array flag:
0 = device not capable of cell array operation.
1 = device capable of cell array operation.
int_out+78, work_out[39] -- Number of available colors:
0 = more than 32,767.
1 = Black and white
2 or more = Number of colors available.
int_out+80, work_out[40] -- Locator input devices:
1 = keyboard.
2 = keyboard and mouse (or other device)
int_out+82, work_out[41] -- Valuator input devices:
1 = keyboard.
2 = other device.
int_out+84, work_out[42] -- Choice devices:
1 = function keys.
2 = other keypad.
int_out+86, work_out[43] -- Text input devices:
1 = keyboard.
int_out+88, work_out[44] -- Type of workstation:
0 = output.
1 = input.
2 = input and output.
3 = reserved
4 = metafile output.
pts_out, work_out[45] -- Minimum character width.
pts_out+2, work_out[46] -- Minimum character height.
pts_out+4, work_out[47] -- Maximum character width.
pts_out+6, work_out[48] -- Maximum character height.
pts_out+8, work_out[49] -- Minimum line width.
pts_out+10, work_out[50] -- 0.
pts_out+12, work_out[51] -- Maximum line width.
pts_out+14, work_out[52] -- 0.
pts_out+16, work_out[53] -- Minimum marker width.
pts_out+18, work_out[54] -- Minimum marker height.
pts_out+20, work_out[55] -- Maximum marker width.
pts_out+22, work_out[56] -- Maximum marker height.
Don't let all this information intimidate you. Right
now, we're only concerned with the three values returned in
*contrl+4*, *contrl+8*, and *contrl+12*. *Contrl+12* will
contain the handle to our virtual workstation, *contrl+4*
will contain the number of points (two values each) returned
in *pts_out*, and *contrl+8* will contain the number of
integers returned in *int_out*. For this function call,
*contrl+4* should contain a 6 after the call, which mean six
pairs of integers have been returned in *pts_out*, and
*contrl+8* should contain a 45, the number of integers
returned in *int_out*. For every VDI call, *contrl+4* and
*contrl+8* are used the same way. You can always check them
to see how many values have been returned by a VDI function.
Finally, in the above example, notice that we are
calling a subroutine called *vdi* to perform a VDI function.
The *vdi* subroutine works similarly to the *aes*
subroutine, setting up the VDI function and then doing a
*trap #2*.
--Clearing the Workstation--
The last step in getting the VDI initialized is to clear the
workstation. Clearing a workstation ensures that all the
devices have been flushed and the screen has been erased. In
other words, it presents us with a blank slate upon which
our program can begin to operate. To clear a workstation, we
call VDI function #3, *v_clrwk*, like this:
move #3,contrl
clr contrl+2
clr contrl+6
move vws_handle,contrl+12
jsr vdi
As you can see, this function has no special
parameters, nor does it return any values. It simply does
its business and returns control to the program. Notice
again, how we're using the control array. Because we have no
values in the *pts_in* and *int_in* arrays, we set both
*contrl+2* and *contrl+6* to 0. When calling a VDI function,
you also must be sure that the virtual workstation handle is
in *contrl+12*. In the above example, we show the
workstation handle being placed in *contrl+12*. However, in
the sample program, this instruction is missing. Why?
Because the handle is already in *contrl+12*, where it was
placed by the call to *v_opnvwk*. The handle will stay in
*contrl+12*, right where we want it, until we overwrite it.
--Polylines--
Now that we've got our workstation set up, we can get down
to business. The first graphic we'll experiment with is the
polyline. Those of you who are up on your linguistics know
that the prefix "poly" means "many." A polyline is one or
more lines connected from point to point, which allows the
programmer to draw complex shapes with a single function
call.
But before we draw our polylines, we need to set some
line attributes, like color, width, and end style. Any lines
drawn after we've set the attributes will use those
attributes. Also, the line attributes stay in effect until
we change them again.
To set a line's color, we use a call to VDI function
#17, *vsl_color*, like this:
move #17,contrl
clr contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move color,int_in
jsr vdi
Here, *color* is an integer from 0 to the device
maximum (low resolution=15, medium resolution=3, and high
resolution=1). If we use a number higher than the maximum,
the function will default to color 1. On the ST, the default
color palette, starting with 0 and ending with 15, is white,
black, red, green, blue, cyan, yellow, magenta, white,
black, light red, light green, light blue, light cyan, light
yellow and light magenta. The actual color value set is
returned in *int_out*.
When we're drawing lines, we can also choose an end
style with a call to VDI function #108, *vsl_ends*:
move #108,contrl
clr contrl+2
move #2,contrl+6
move vws_handle,contrl+12
move ends,int_in
move ends,int_in+2
jsr vdi
In this case, *ends* is an integer value from 0 to 2. A
value of 0 will yield a square end, 1 will get us an arrow,
and 2 will result in a rounded end. Here we're using *ends*
as both the beginning and ending line style, but each end of
the line can have a different end style if we like. To do
this, we'd put the first end style in *int_in* and the
second end style in *int_in+2*. This function returns no
values.
Finally, we can set the thickness of our lines with a
call to VDI function #16, *vsl_width*:
move #16,contrl
move #1,contrl+2
clr contrl+6
move vws_handle,contrl+12
move width,pts_in
clr pts_in+2
jsr vdi
The variable *width*, which is placed into the first
element of *pts_in*, must be an odd positive integer. The
line will be set to the closest width less than or equal to
the value of *width*. Notice that, for some strange reason,
*pts_in+2* must contain a 0. The actual width set is
returned in the first element of *pts_out*.
Once we have the attributes set, we can draw our first
line. We do this with a call to VDI function #6, *v_pline*:
move #6,contrl
move #2,contrl+2
clr contrl+6
move vws_handle,contrl+12
move x1,pts_in
move y1,pts_in+2
move x2,pts_in+4
move y2,pts_in+6
jsr vdi
In this call, *x1* and *y1* are the X and Y coordinates
of one end of the line. The integers *x2* and *y2* are, of
course, the X and Y coordinates of the other end of the
line. In the example program, we're using *v_pline* to draw
only single lines. However, as we said before, this function
can be used to draw many connected lines. For example, to
extend the above example so that it draws two connected
lines, we could do something like this:
move #6,contrl
move #3,contrl+2
clr contrl+6
move vws_handle,contrl+12
move x1,pts_in
move y1,pts_in+2
move x2,pts_in+4
move y2,pts_in+6
move x3,pts_in+8
move y3,pts_in+10
jsr vdi
Notice that we are now loading a 3 into *contrl+2*,
because the *pts_in* array now contains three points.
(Remember, a point is really two values.) We've also loaded
the values *x3* and *y3* (the new point) into the next two
elements of the *pts_in* array. These values are the next
point to which the *v_pline* function should draw. We could
continue drawing lines by adding more and more points to the
*pts_in* array. We just must be sure that the value in
*contrl+2* is the total number of points in the array,
otherwise the function will ignore some of the points.
If we're drawing a polyline at the smallest width, we
can choose between six system line types with a call to VDI
function #15, *vsl_type*:
move #15,contrl
clr contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move type,int_in
jsr vdi
Here, *type* is an integer value from 1 to 7 as follows:
1 solid ________________
2 long dash ___ ___ ___ ___
3 dots ...............
4 dash dot __.__.__.__.__.
5 dash __ __ __ __ __ __
6 dash dot dot __..__..__..__..__
7 user defined
Type 7 lets you set up your own line types, but we're
not going to get into that now. This function returns, in
*int_out*, the actual line type set.
Now that we've covered the basics of setting up the VDI
and calling graphics functions, let's take a quick look at
some of the other graphics you can draw with the VDI.
--Rectangles--
We can use *v_pline* to draw a standard square-cornered box,
but the VDI also supplies a function that will let us draw
rectangles with rounded corners. To do this, we call VDI
function #11, sub-function #8, *v_rbox*:
move #11,contrl
move #2,contrl+2
clr contrl+6
move #8,contrl+10
move vws_handle,contrl+12
move x1,pts_in
move y1,pts_in+2
move x2,pts_in+4
move y2,pts_in+6
jsr vdi
Here, we must supply the pixel coordinates of the
upper-left and lower-right corners. We place these values
into the *pts_in* array. Also note that this function call
requires that you place a sub-function number (8) into
*contrl+10*. The line attributes--color, style and width--
are used with *v_rbox*, allowing a wide variety of
rectangles. This function returns no values.
You can also draw a filled rounded rectangle, using VDI
function #11, sub-function #9, *v_rfbox*:
move #11,contrl
move #2,contrl+2
clr contrl+6
move #9,contrl+10
move vws_handle,contrl+12
move x1,pts_in
move y1,pts_in+2
move x2,pts_in+4
move y2,pts_in+6
jsr vdi
This function uses the currently active fill pattern,
which we'll learn to set later on.
To draw a filled rectangle with square corners, use VDI
function #11, sub-function #1, *v_bar*:
move #11,contrl
move #2,contrl+2
move #0,contrl+6
move #1,contrl+10
move vws_handle,contrl+12
move x1,pts_in
move y1,pts_in+2
move x2,pts_in+4
move y2,pts_in+6
jsr vdi
As you may suspect, this function, too, uses the
current fill pattern.
--Circles, Ellipses, and Arcs--
GEM's VDI provides several functions for drawing
various types of curved lines and shapes. If you'd like to
draw a filled circle, just use VDI Function #11, sub-
function #4, *v_circle*:
move #11,contrl
move #3,contrl+2
move #0,contrl+6
move #4,contrl+10
move vws_handle,contrl+12
move centerx,pts_in
move centery,pts_in+2
move #0,pts_in+4
move #0,pts_in+6
move radius,pts_in+8
move #0,pts_in+10
jsr vdi
Here, *centerx* and *centery* are the X and Y
coordinates of the circle's center, and *radius* is the
circle's radius. Note that *pts_in+4*, *pts_in+6*, and
*pts_in+10* all contain dummy arguments of 0. The *v_circle*
function, like *v_rfbox*, uses the current fill attributes.
You can draw ellipses, too. An ellipse looks something
like a squashed circle or a solid oval and is drawn by a
call to VDI function #11, sub-function 5, *v_ellipse*:
move #11,contrl
move #2,contrl+2
move #0,contrl+6
move #5,contrl+10
move vws_handle,contrl+12
move x,pts_in
move y,pts_in+2
move hrad,pts_in+4
move vrad,pts_in+6
jsr vdi
Here, the parameters *x* and *y* denote the ellipse's
center point, and *hrad* and *vrad* are the X and Y radiuses
in pixels. Once again, the active fill attributes are used.
No values are returned from the function.
Arcs are curved lines and are easy to draw with VDI
function #11, sub-function #2, *v_arc*:
move #11,contrl
move #4,contrl+2
move #2,contrl+6
move #2,contrl+10
move vws_handle,contrl+12
move angle1,int_in
move angle2,int_in+2
move x,pts_in
move y,pts_in+2
move #0,pts_in+4
move #0,pts_in+6
move #0,pts_in+8
move #0,pts_in+10
move rad,pts_in+12
move #0,pts_in+14
jsr vdi
The parameters *x*, *y*, and *rad* are the X,Y-
coordinates of the center and the radius, respectively. The
integers *angle1* and *angle2* are the beginning and ending
angles of the arc, in tenths of degrees (that is, values
from 1 to 3600). Note that *pts_in+4*, *pts_in+6*,
*pts_in+8*, *pts_in+10*, and *pts_in+14* all contain dummy
arguments that must contain zeroes. No value is returned
from the function.
The final call in this family of functions allows you
to draw pie slices, which help you to draw pie charts. To
draw a pie slice, use a call to VDI function #11, sub-
function #3, *v_pieslice*:
move #11,contrl
move #4,contrl+2
move #2,contrl+6
move #3,contrl+10
move vws_handle,contrl+12
move angle1,int_in
move angle2,int_in+2
move x,pts_in
move y,pts_in+2
move #0,pts_in+4
move #0,pts_in+6
move #0,pts_in+8
move #0,pts_in+10
move rad,pts_in+12
move #0,pts_in+14
jsr vdi
The parameters here are the same as those for the arc
function. However, the body of the pie slice will be colored
by whatever fill pattern is active. This function returns no
values.
--Polymarkers--
Polymarkers are a number of predefined shapes you can
use in your graphics. To draw them, you call VDI function
#7, *v_pmarker*:
move #7,contrl
move #3,contrl+2
move #0,contrl+6
move vws_handle,contrl+12
move x1,pts_in
move y1,pts_in+2
move x2,pts_in+4
move y2,pts_in+6
move x3,pts_in+8
move y3,pts_in+10
jsr vdi
The parameter placed in *contrl+2* is the number of
markers you want to draw. The X,Y coordinates for the
markers are stored in the *pts_in* array. The above example
shows three markers being drawn, but you can draw as many as
you need. This function returns no values.
What do these markers look like? You have a choice of
six predefined shapes which (from 1 to 6, respectively) are
dot, plus sign, asterisk, square, diagonal cross, and
diamond. To set the polymarker type, call VDI function #18,
*vsm_type*:
move #18,contrl
move #0,contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move type,int_in
jsr vdi
Here, *type* is a value from 1 to 6. If you should
choose a value out of this range, the function will select
the asterisk as a default. The value chosen will be returned
in *int_out*.
There are two other attributes that affect polymarkers:
color and height. Color is set with a call to VDI function
#20, *vsm_color*:
move #20,contrl
move #0,contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move color,int_in
jsr vdi
Here, *color* is a value from 0 to the device maximum.
All the rules of the *vsl_color* call apply in this case.
The actual color set is returned in *int_out*.
You can change the size of all polymarkers, except the
dot (which always appears in the smallest size), with a call
to VDI function #19, *vsm_height*:
move #19,contrl
move #1,contrl+2
move #0,contrl+6
move vws_handle,contrl+12
move #0,pts_in
move height,pts_in+2
jsr vdi
The parameter *height* is the polymarker's size on the
Y-axis. The actual height will be the greatest height
available on the device, less than or equal to the height
parameter. This will be returned in *pts_out+2*. Note that,
in the above function call, *pts_in* is always 0, with the
requested height being placed in *pts_in+2*.
--Fill Patterns--
GEM supplies many patterns we can use to fill our figures.
There's a series of functions to let us set these patterns
up the way we want them. The first step is a call to VDI
function #23, *vsf_interior*:
move #23,contrl
move #0,contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move pattern,int_in
jsr vdi
Here, *pattern* is a value from 0 to 4. The values are
interpreted as follows:
0 Hollow (background color)
1 Solid
2 Pattern
3 Hatch
4 User-defined
The actual pattern set is returned in *int_out*.
If you choose style 0 or 1, you need go no further, but
style 2 allows you to choose between 24 different patterns,
and style 3 provides 12 hatch styles. You choose the pattern
you wish to use, with a call to VDI function #24,
*vsf_style*:
move #24,contrl
move #0,contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move fill,int_in
jsr vdi
Here, *fill* is a value from 0 to 23. Consult your reference
manual to see what these styles look like. The fill that was
actually set is returned in *int_out*.
The color of the fill is selected with a call to VDI
function #25, *vsf_color*:
move #25,contrl
move #0,contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move color,int_in
jsr vdi
All the rules for the *vsl_color* function apply here,
also, with the actual color that was set returned in
*int_out*.
Finally, you can choose between a visible or invisible
border for your fill with a call to VDI function #104,
*vsf_perimeter*:
move #104,contrl
move #0,contrl+2
move #1,contrl+6
move vws_handle,contrl+12
move flag,int_in
jsr vdi
Here, a *flag* value of 0 will give you an invisible
border. Any other value will cause the border to be drawn in
the current fill color.
--Conclusion--
Now that you've been introduced to many of the graphics
functions available to you through the VDI, study the sample
program to see them in action, then take some time and
experiment with the VDI on your own. See if you can write a
program to draw a simple picture, or maybe a graph.
--Summary--
* The VDI (Virtual Device Interface) controls most of the
ST's graphic capabilities and provides some mouse and cursor
control functions, as well.
* You call VDI functions much like you call AES functions,
by placing appropriate values into control and input arrays,
and then calling the function by using a *trap #2*
instruction.
* To initialize the VDI, you must get a handle to the
physical screen, open a virtual workstation, and finally
clear the workstation.
* The AES function #77, *graf_handle*, obtains a handle to
the physical workstation and returns information about the
system font.
* The VDI function #100, *v_opnvwk*, obtains a handle to a
virtual workstation.
* The VDI function #3, *v_clrwk*, clears a workstation,
flushing all devices and clearing the screen.
* The VDI functions *vsl_color* (#17), *vsl_ends* (#108),
*vsl_width* (#16), and *vsl_type* (#15) set various line
attributes.
* The VDI function #6, *v_pline*, draws polylines.
* Other shapes can be drawn using the VDI functions *v_rbox*
(#11,8), *v_rfbox* (#11,9), *v_bar* (#11,1), *v_circle*
(#11,4), *v_ellipse* (#11,5), *v_arc* (#11,2), and
*v_pieslice* (#11,3).
* Polymarkers are drawn by VDI function #7, *v_pmarker*.
* The polymarker attributes can be set by the VDI functions
*vsm_type* (#18), *vsm_color* (#20), and *vsm_height* (#19).
* The current fill pattern's attributes can be set by the
VDI functions *vsf_interior* (#23), *vsf_style* (#24),
*vsf_color* (#25), and *vsf_perimeter* (#104).
CW_PROG5.S (Source of the chapiter)
CW_PROG5MAC.S (Source of the chapiter)
Back to Assembly_language_tutorials