COURS208.TXT
****************************************************************** * * * 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