Skip to main content

PROGRAMMING A SIMPLE ACCESSORY IN MACHINE CODE
By Stefan Posthuma

When I was browsing through some old disks of mine, I ran across
a little source file called 'FREERAM.ASM'. It was the source of a
true accessory that showed the amount of free RAM available. I
wrote it a long time ago, when I ran across an accessory skeleton
somewhere in some book or magazine. (I forgot where I found it).

Lots of people have an alternative fileselector these days. Now
some of them are fairly simple, but others (like the UMS II) are
so extensive that they are even more easy to use than the
desktop! I found myself starting application programs just to be
able to access the fileselector so I could move some files, or
rename a folder.

Funny...
At the very moment I typed this, strange images of purple
creatures clad in orange robes drift through my mind. Something
tells me that these images are not a production of my own mind,
but things transmitted through the endless voids of space and
time. The creatures seem to be involved in some sort of ritual
but this image is too hazy to understand totally...

So I got the idea to make an accessory that calls the
fileselector and ignores whatever it returns. This would solve
the problem of having to start a program to be able to use the
filselector. I dug up my GEM book and started programming, and
about half an hour later, it was there. 'Filesel.acc', ready to
be put in the boot directory of my hard disk.

There is a lot to programming GEM, and I assume you are at least
a bit familiar with it. You must be familiar with terms like
INT_IN and ADDR_OUT. Those that are not interested in the
technical details, the 'FILESEL.ACC' file can be found in the
PROGRAMS folder on disk 1 (in the directory DISK_1.A), the source
can be found there as well, called FILESEL.S

Ok, an explanation of the source is to follow. What every GEM
program needs, is an AES Parameter Block. This is a list of
arrays that are used to pass parameters to and from the AES. For
each call, we have to supply the number of values to be passed,
the number of addresses to be passed, the number of values to be
received and the number of addresses to be received.
The array intin is used to store all numerical parameters of the
AES call. The array addrin is used for all addresses that have to
be passed to the function. Intout and addrout return values.

aespb dc.l contrl,global,intin,intout,addrin,addrout

grhandle ds.w 1 ; graphic handle
appid ds.w 1 ; application ID
accid ds.w 1 ; accessory ID
msgbuff ds.b 16 ; message buffer
ds.l 128
newstack ds.l 1 program stack

; control block
contrl
opcode ds.w 1 ; AES call #
sintin ds.w 1 ; number of INTIN values
sintout ds.w 1 ; number of INOUT values
saddrin ds.w 1 ; number of ADDRIN values
saddrout ds.l 1 ; number of ADDROUT values
ds.w 5
global: ds.l 8

; the parameter arrays
intin ds.w 80
ptsin ds.w 80
intout ds.w 80
ptsout ds.w 80
addrin ds.w 80
addrout ds.w 80

Now we need a routine that calls the AES. This is done by loading
D0 with C8, loading D1 with the address of the parameter block
and calling TRAP #2:

aes move.l #aespb,d1
move.w #$c8,d0
trap #2
rts

We have to assign a local stack:

start lea newstack(pc),sp

...The image gets stronger now. The creatures are chanting in an
alien tongue and little tentacles and strange fumes are
protruding from their bodies. What this has got to do with this
article I do not know but the image is so strong...

What every GEM program has to do, is to make itself known to GEM.
This is done by the appl_init() call which takes no parameters
and returns the application ID, a number used by GEM to refer to
this program.

; AES 10: appl_init()
move.w #10,opcode
move.w #0,sintin
move.w #1,sintout
move.w #0,saddrin
move.w #0,saddrout
bsr aes
move.w intout,appid

Next we need the graphic handle for this program so it can use
VDI to draw dialog boxes etc. It returns the graphic handle plus
some font information which we don't need.

; AES 77: graph_handle()
move.w #77,opcode
move.w #5,sintout
move.w #0,saddrin
move.w #0,saddrout
bsr aes
move.w intout,grhandle

After that, we have to make sure our accessory appears in any
upcoming menu bar. We have to pass the accessory name plus the
application ID to the menu_register() function. This will also
return the accessory ID which we will need to identify our
accessory:

; AES 35: menu_register()
move.w #35,opcode
move.w #1,sintin
move.w #1,sintout
move.w #1,saddrin
move.w appid,intin
move.l #accname,addrin
bsr aes
move.w intout,accid

'accname' holds the name of the accessory that will appear in
the desk menu:

accname dc.b " Fileselector ",0

After all this, we have to wait until the accessory gets
activated, and call the fileselector. Waiting for activation is
done by the infamous event_multi() call. This sucker takes 13
parameters and is called in the 'event' routine. It will return
after something happens to the program. This can be the resizing
of a window, the clicking of a button or, in our case, the
activation of an accessory. The message buffer will contain an
event number. We have to check this to see if it was indeed an
AC_OPEN (40) event. Then we have to see if our accessory was
called by checking the accessory ID. If it was our accessory, we
can call the fileselector.

loop bsr event
cmp.w #40,msgbuff ; AC_OPEN?
bne.s loop
move.w msgbuff+8,d0
cmp.w accid,d0 ; our accessory?
bne.s loop
bsr run ; yes, do the voodoo
bra.s loop

...Apparently, the creatures are reaching some sort of climax in
their bizarre ritual. It seems to me that they have constructed a
small puppet that looks familiar. They also operate a strange
device and their tongue starts becoming more and more
understandable...

What we will do now, is to build the current path. This is
achieved by calling a GEMDOS($19) to get the drive letter and a
GEMDOS($47) to get the current path. This will be stored in
fs_iinpath will which be passed to the fileselector after we have
appended the file mask (*.*) to it.

run move.w #$19,-(sp) ; get drive letter
trap #1
addq.l #2,sp
add.b #'A',d0
move.b d0,fs_iinpath ; move to pathname
move.b #':',fs_iinpath+1 ; colon next to it

clr.w -(sp) ; get current directory
pea fs_iinpath+2(pc); put it here
move.w #$47,-(sp)
trap #1
addq.l #8,sp
lea mask(pc),a0 ; copy *.* to path
lea fs_iinpath(pc),a1
test tst.b (a1) + ; find end of string
bne test
subq.w #1,a1
bsr strcpy
lea name(pc),a0 ; copy name
lea fs_insel(pc),a1
bsr.s strcpy

After all this hard work, we can finally call the fileselector.
It takes two addresses, the address of the path and the address
of the default filename. Pitfall here is that it will also store
the selected path+name here so you have to make sure there is
enough space to store them! (I got some interesting crashes...)

; AES 90: Fsel_Input
move.w #90,contrl
move.w #0,contrl+2
move.w #2,contrl+4
move.w #2,contrl+6
move.w #0,contrl+8
move.l #fs_iinpath,addrin
move.l #fs_insel,addrin+4
bsr.s aes
rts

Nice routine to copy string pointed to by A0 to space pointed to
by A1. String must end with a 0 byte.
strcpy move.b (a0)+,(a1)
tst.b (a1)+
bne.s strcpy
rts

Finally, the event_multi call. This takes so many parameters,
that a table is used to pass them all. This table is copied to
intin.

; AES 25: Event_multi
event move.w #25,opcode
move.w #16,sintin
move.w #7,sintout
move.w #1,saddrin
move.l #msgbuff,addrin
lea table(pc),a1
lea intin(pc),a2
moveq #15,d0
lop1 move.b (a1)+,(a2)+
dbra d0,lop1
bsr.s aes
rts

table dc.w $13,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0

Filemask and default file name are stored here:

mask dc.b "\*.*",0
name dc.b 0

This space is used to pass and return path and file name:

fs_iinpath: ds.b 128
fs_insel: ds.b 16

Well, that's all there is to it. I think it is surprisingly easy
and with some nafty macro's, GEM programming in machine code is a
piece of brunost! (only Norwegians will get this one)

...The images are starting to get frightening now. The ritual has
reached its climax and I can now fully understand what they are
saying. Some of them are chanting about the Horrible Changing of
the Pathname and others are busy describing the horrors that will
follow after the Pressing of the Cancel Button. They have
activated the device now. My room is starting to fade away and
suddenly, I am surrounded by the strange creatures.
One of the bigger ones approaches me and addresses me in perfect
English:
"Are you Stefan Posthuma?" it asks in a contemptuous voice.
"Er...yes" I answer somewhat uncertain.
"DESECRATOR!"
"Did you or did you not just write a program for the sole
purpose of serving the blasphemous Alternative Fileselector?"
"Who are you?", I ask even more uncertain.
"HA!"
"We are the militant descendants of the Fileselector Worshippers
of Trelliona 1. Only one of our siblings survived the Holy
Suicide of our tribe and he now heads the Crusade Against
Alternative Fileselectors!! We sentence and execute any creature
that has any connections to the tools of Evil!!"
Slight feelings of discomfort are creeping up my spine as I
watch the slimy aliens ooze and steam away when they discuss what
to do with me.
"Throw him in the Pit of Eternal Digestion!" one suggests.
"No, feed him to the Pandimensional Piranhas of Protuberanta
Phallica!"
"How about tying him to a Shimmerion Sexsavator about to engage
a mating ritual with a Molmerion MegaMutant of Potention IV?"
The creatures got really exited discussing the new ways of
modern limb rearranging for humans and lost interest in me. I
noticed a large computer screen completely filled with the image
of a Fileselector. I also noticed the cancel button on it plus a
poor imitation of an Atari mouse. I acted quickly, much to the
astonishment of the creatures. Fortunately, the mouse worked.
When the creatures understood I was going for the cancel button,
they paniked.
"Click", it went.

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.