******************************************************************
* *
* 68000 ASSEMBLER COURSE ON ATARI ST *
* *
* by The Fierce Rabbit (from 44E) *
* *
* Second series *
* *
* Lesson number 8 *
******************************************************************
I hope you are not approaching this course immediately after having
finished reading the previous one, but, on the contrary, you have
plunged into line A with joy!
We are now going to approach a topic which, I must admit,
scared me a bit at first: the GEM.
In fact, in programming as in many other subjects, one
starts working simply when one is forced to. So I
had only done very small things with the GEM in
assembler, things like office accessories that allow you to
put the screen in reverse video, with a choice in an alert
box, before finding myself faced with the description of software that a
Parisian company proposed to me. I must admit that the first
days were a bit tough, but in the long run, I found that
GEM is really a fabulous thing, not very hard to master,
and the possibilities are more than sufficient to fill with joy any programmer worthy of the name!!! So I hope that you
will take as much pleasure as me in programming under GEM once
you have read this chapter.
First of all, the remarks that are at the beginning of the chapter
on line A, deserve to be reread. So, look for
documentation without worrying about the language. You will find in the
last course of this series a bibliography in which I have
tried to list various very nice articles.
GEM is accessible through TRAP #2, but in fact thanks to this trap
we have access to several parts of the GEM, a bit like if the
trap #1 at the same time led to GEMDOS and BIOS. GEM is,
indeed, composed mainly of 2 parts:
AES and VDI.
VDI routines - VIRTUAL DEVICE INTERFACE -
take care of graphics;
drawing of circles,
ellipse,
lines,
rectangles
etc...
On the other hand, the display of typical GEM objects:
windows,
alert boxes
is performed by the AES - APPLICATION ENVIRONMENT SYSTEM -.
As you discover the VDI and AES functions
you will realize their interaction.
The great advantage of this system can be explained simply: it
seems obvious to everyone that outputting a drawing on a screen,
a diskette or a printer, it's not the same thing.
WRONG! For the GEM it's the same!
In fact, one can say that you have to prepare your drawing and to
say "I am sending it." Where? Ah, there, it's as you wish because for the VDI
the screen,
the plotter,
the disk,
the printer
etc...
are just peripherals. It is enough to designate the peripheral
of our choice and it does the job all alone!!!!
The only problem:
the truly independent routines of the peripherals are
found in GDOS - this name surely makes you shiver with fright...
-- Several programs at the same time?
The principle of GEM is very attractive but must lead us to think
a little bit about the potential mixing of data. In fact, even if it is not truly multitasking (to be multitasking consists in being able to run applications exactly
at the same time, which is anyway impossible with a 68000)
GEM, therefore, allows having several programs active at the same
time, in this case a main program and 6 accessories.
For GEM there is fundamentally no difference between a
PRG and an ACC and, for this reason, in GEM vocabulary, we
call them "applications". GEM can therefore find itself with managing 7 applications,
each potentially having several windows. One can easily imagine the mess in memory!!!
-- How does GEM manage it?
At the launch of an application, it calls the AP-
PL_INIT function (Application_Init). This function notifies GEM that our
application wants to become active, and GEM responds by providing us
with a number, the APP_ID (Application Identifier) which
will now serve as a reference. Our application will therefore be
for example number 3, and will be recognized as such by GEM. Attention, the APP_ID is only given
to the application for the duration of its
presence in memory. If I launch an ACC on Monday, it
can inherit the APP_ID 4 but if I launch it again on Tuesday under different
conditions, it can get the APP_ID 5. However, it
will keep this APP_ID for all its activity.
When we open a window, it's the same principle. GEM
provides what we call a HANDLE, that is to say, a number corresponding to the window. In fact, the HANDLE is the identification number of a window but potentially also of a device.
-- Multitasking?
One of the most important parts of GEM concerns the management
of events. An event is an action from the user of
the machine: mouse click, pressing a key etc... In fact, under
GEM the applications spend most of their time
waiting. Imagine a PRG with an open window and a dropdown menu, and at the same time in memory 3 accessories. I go to
the accessories menu. The menu unfolds and the titles appear
in reverse video when the mouse passes over them. All this is
done by GEM, all alone like a big boy. I click on the title
of accessory 2.
GEM detects the click, knows that I am in the accessories, looks
at which entry I clicked on. As GEM assigned the
entries to the ACCs, it sends a message to accessory 2
to tell it "you need to open up". So it opens up, and
displays a window on the screen. So we have 2 windows at the same
time. I click on the PRG's window, GEM looks to whom the window belongs
and sends a message to the PRG to tell it "we have activated
your window number XX" etc... So we are going to build in
our GEM programs, a core of actions monitoring, and
we will react according to these actions.
-- To call GEM functions.
Calls are made with parameters that we pass in arrays. As we use DEVPACK, we will use its library. Indeed, for calls to GEM, the parameters are
numerous and to be placed in very specific places in the arrays.
For these reasons, macros are very useful here. We will
therefore call the GEM functions with the macros contained
in the DEVPACK library. However, it is also necessary to know
the arrays, in order to be able to perfectly understand the
principle of operation.
For AES, 6 arrays are needed:
CONTROL,
GLOBAL,
INT_IN,
INT_OUT,
ADDR_IN,
ADDR_OUT.
For VDI, 5 arrays are needed:
CONTRL,
INTIN,
INTOUT,
PTSIN,
PTSOUT.
Pay attention to the slight spelling difference between INT_IN and
INTIN ! To indicate, during the call to GEM, where it
will find these arrays, their addresses are placed in 2 lists:
One for AES:
aes_params dc.l control, global, int_in, int_out, addr_in, addr_out
and one for VDI:
vdi_params dc.l contrl, intin, ptsin, intout, ptsout
Here are the arrays as they are defined in the DEVPACK
GEM library:
control ds.w 5
global ds.w 14
int_in ds.w 16
int_out ds.w 7
addr_in ds.l 3
addr_out ds.l 1
contrl ds.w 1
contrl1 ds.w 1
contrl2 ds.w 1
contrl3 ds.w 1
contrl4 ds.w 1
contrl5 ds.w 1
contrl6 ds.w 1
contrl7 ds.w 1
contrl8 ds.w 1
contrl9 ds.w 1
contrl10 ds.w 1
contrl11 ds.w 1
intin ds.w 128 min 30
intout ds.w 128 min 45
ptsin ds.w 128 min 30
ptsout ds.w 128 min 12
You will notice the strange setup of the CONTRL arrays (array
for VDI). Indeed it is often necessary to pass parameters
'by hand' into this array. With this system, it will be possible to
perform an operation like MOVE.W #10,CONTRL2
Pay attention, this numbering of CONTRL corresponds to the number of
words because each of the entries is defined by DS.W and not by
DS.B!!! This is explained by the fact that 99% of the documents related
to GEM are for 'C' and that is the type of command that is
made in 'C'. Thus you will find often; "put 10 in
contrl(2)"; you just have to do MOVE.W #10,CONTRL2 and it's done.
-- Why so many arrays? Because each of these arrays is
meant to receive or to return a certain type of data.
Let's see a quick description of these arrays.
AES Arrays
** control
Designed to contain, in order:
number of the function (.W),
number of bytes of INT_IN (.W),
number of bytes of INT_OUT (.W),
number of long words of ADDR_IN (.W)
number of long words of ADDR_OUT
** global
This array is a bit special, and the explanations concerning it are of no use in the context of these courses. Once well absorbed the rest, you can always look into it, but
currently, this would only confuse you! (See bibliography for more)
** int_in
This array is intended to receive integer values (Integer
In) that AES will need.
For example, a window number.
** int_out
The opposite of the previous one, this array returns results, for example
if you ask for the available surface for a window, you
will have the dimensions here.
** addr_in
List in which you can place addresses
** addr_out
and here, you can read them! In fact, it suffices, like
always, to read the name of the array to deduce what it
contains!
VDI Arrays
** contrl
In contrl0 we place the opcode of the function, as it is called
its number.
In contrl1 we place the number of data that will be put
in the INTIN array
In contrl2 we place the number of points (so pairs of
data) that will be placed in the PTSIN array
In contrl3 we will place the sub-function identifier.
For example, the drawing of circles, ellipses, rectangles etc... is
done with function 11. A sub-code is therefore necessary to
define which module within function 11 we wish to use.
In contrl6 we place the handle of the device. (see above)
Starting from contrl7 there are sometimes pieces of information to pass,
depending on the function.
** intin and ptsin
We will then fill the INTIN array with the integer parameters
required by the function and the PTSIN array with the coordinates
required by the function. Once the function is called,
we will retrieve:
in contrl2 the number of pairs of coordinates of ptsout and
in contrl4 the number of words of intout.
Here is a call to GEM. This function displays a sentence where one
wants on the screen, unlike Gemdos (9) which is limited to lines and text columns. Moreover, this function allows
to display text with effects (bold, underline, etc...) with
the font of our choice:
LEA MESSAGE,A1 address of the sentence
LEA INTIN,A0 receiving table
MOVEQ.L #0,D2 init the letter counter
HERE3 CLR.W D0
MOVE.B (A1)+,D0 takes in bytes
BEQ GO_ON end of the text
ADDQ.B #1,D2 we count the letters
MOVE.W D0,(A0)+ transfer to INTIN (in words)
BRA HERE
GO_ON MOVE.W #100,PTSIN X position
MOVE.W #150,PTSIN+2 Y position
MOVE.W D2,CONTRL3 number of letters
MOVE.W #1,CONTRL1
MOVE.W CURRENT_HANDLE,CONTRL6
MOVE.W #8,CONTRL opcode
MOVE.L #VDI_PARAMS,D1
MOVE.W #$73,D0
TRAP #2
AAAAAAAAAARRRRRRGGGLLL!!!!!! It's a horror, isn't it!
You must arm yourself with patience and dissect the multiple calls to GEM.
To help you with your tests, you will find enclosed a file
named GEM. It contains the source of an ACC that displays an
alert box, of a PRG that manages a resource (listing from
WERCS) and of an accessory that manages a window. Regarding resource editors, I work with K Resource which is very
nice and does not crash, unlike Wercs!
Try to understand the principle well: display an alert
box with a single button, then with several, make small
simple resources, then more and more complicated ones etc... The principle will always remain the same no matter how big your application is. Try to make small accessories
such as disk formatters, with a small form
that asks if you want to format disk A or B, simple or double-sided etc...
With these examples, you should be able to manage.
That's how I started! Also take a look at the bibliography, there are some interesting things!
Back to ASM_Tutorial