Intro
Hi again! Last time we met I talked about the `correct way' (MHO!) of setting
up a Project for our first program. This time we will look at libraries.
I am afraid this piece may seem a bit out of sequence. But when trying to
examine libraries a lot of other issues are uncovered. It would be too easy
to keep saying "this will be discussed later", but we'll briefly
look at them as they crop up. Libraries can be very useful and go some way
to modularising your code, as well as making the overall flow of your program
more readable.
What Is A Library?
A library is just some pre-written, pre-tested code that you can use in
your program. LightSoft supply a number of libraries.
We're going to jump straight into it - so take a deep breath.
Before we can run any program there are certain `warm up' routines that need to be carried out before we can see our program in action. To cut to the chase, they are called `initialisation routines'.
(This is where things may seem a bit jumbled up. Read on, all will become clear.)
Program Initialisation
For any Macintosh program to work we first have to 'initialise' the program
and get it ready to run. As you may know most of the basic stuff (drawing
a rectangle, opening a window, saving a file, etc.) are implemented as Toolbox
calls in the Mac's ROM. When you want to open a window, you just call the
appropriate Toolbox call.
/* Standard Mac Initialization */ InitGraf(thePort); /* Initialise Graphics InitFonts( ); /* Initialise Font InitWindows( ); /* Initialise Windows InitMenus( ); /* Initialise Menus TEInit( ); /* Initialise built-in Text Editor InitDialogs( 0L ); /* Initialise Dialogs FlushEvents( everyEvent, 0 ); /* Initialise Events InitCursor( ); /* Initialise Cursor
In Fantasm the same initialisation could look like this:
; Standard Mac Initialisation LEA quickdraw_globals(PC),A0 ; QuickDraw work space LEA 202(A0),A0 ; Add 202 to A0 quickly MOVE.L A0,-(SP) DC.W _InitGraf ; Initialise Graphics DC.W _InitFonts ; Initialise Fonts MOVEQ #-1,D0 DC.W _FlushEvents ; Initialise Events (parameter in DO) DC.W _InitWindows ; Initialise Windows DC.W _InitMenus ; Initialise Menus CLR.L -(SP) DC.W _InitDialogs ; Initialise Dialogs DC.W _TEInit ; Initialise built-in Text Editor DC.W _InitCursor ; Initialise Cursor
But those wonderful characters at Lightsoft gave us `libraries'. (See I told you we'd get back to discussing libraries!) Libraries can make things a lot easier. Instead of using those 13 lines every time we want to initialise our program we can simply use:
BSR A5_Init ; Standard A5 Initialisation BSR Init_Mac ; Standard Mac Initialisation
Just 2 lines! Both of these libraries are part of the supplied LS Standard Libraries. I'm sure you'll agree they certainly make things a lot more understandable.
FYI #2
While the above is pretty accurate, we also must remember to define the
libraries we use at the end of our source file, like this :
EXTERN Init_Mac,A5_Init
`Init_mac.s' is a fairly core and very important example of a library. Lightsoft supply a standard set of libraries you can use, but you can create your own too. A library can contain any standard routines that you create for use in your own programs.
For instance, if you find that you need code to trap for a key press, you may want to write the code once and make it a library function. After all, there are probably a lot of uses for this particular library function. Then all you need to do is call that library function, pass it the parameters it needs and then trap for the return value. Pretty much like using a Toolbox call.
In the above picture you can see an example library which contains 4 library functions. So lets say you want to use the `WaitKey' function. First, we need to set our Projects paths to where our library lives. Put your libraries in an appropriately named folder and select that folder in the PowerFantasm>Project>Project setup>Paths window. Now your Project file knows where the libraries you want to use live.
Second, we need to tell our source code that we are going to use one of those library functions in that source code file.
Finally, we call our library function, pass it the parameters we have set up and see what value it returned - if any.
A couple of points before we move on. First, try to make your libraries and library functions as generic as possible. In this context I mean, it should have a `good shelf life', something that will be useful in a number of programs not just for the program you are writing. It is okay to write a library function as a one off.
Second, it is good practice to write your libraries functions so they can be treated as `magic boxes'. To explain, write your libraries so that when you come to use them you don't need to worry about what is going on inside. Lets say you have a library function that resizes a window. Ideally you should only need to pass it the current window pointer, the current size of that window, what dimensions it should be resized at and the actual physical resizing of the window.
(Rob Probin has written some excellent pieces regarding modular programming and routines in general.) Go to modular programming and routines
Sorry, but... Unfortunately, what started out as a rather straightforward article is getting a bit out of focus. To break the monotony, lets move on. It looks like I'll have to write a more in-depth piece for next time. Sorry folks.
Our First Library
Probably one of the biggest hassles in most compilers is the whole issue
of creating and using libraries. While the method of creating or using them
in PowerFantasm is not terribly complex there are a few things we need to
be aware of when creating our library functions.
Well LightSoft aren't like the other compiler makers. They have a Librarian (catchy name guys!) that makes the process of creating libraries dead easy.
This section details the mechanics of creating a library which contains 1 function. This particular function was stolen from the `IO_LIB.S' file supplied by Lightsoft. (Sorry, but I was looking for something that was going to appeal to a wide audience and was fairly 'reusable'.)
Step 1 : Create A Library
Launch the Librarian. From the File menu select `Create new 68k library'.
A standard file dialog box is displayed. Navigate to your programs libraries
folder and open it. Name the library `First Library' (or something similar)
and click OK. The library window will display the name of your library in
the windows title.
Quit the Librarian for now.
Step 2 : Writing The Function
Launch Eddie, open a new file and type in the following code (or just use
copy and paste) :
Title "WaitKey : Waits for and returns the result of a key press." Title "Good general function that has a 'long shelf life'" Input "None" Output "None" WAIT_KEY: MOVEM.L D1-D2/A0-A4,-(SP) ; Save registers WK1: CLR.B -(A7) MOVE.W #-1,-(SP) LEA EVENTS_BUFF(PC),A3 MOVE.L A3,-(A7) DC.W 43376 ; GetNextEvent as a decimal number MOVE.B (A7)+,D2 TST.B D2 BEQ.S WK1 ; Wait for something LEA EVENTS_BUFF(PC),A4 MOVE.W (A4),D2 CMPI.W #3,D2 ; Key? BEQ.S WAIT_KEY_END CMPI.W #1,D2 ; Mouse button? BEQ.S WAIT_KEY_END BRA.S WK1 WAIT_KEY_END: MOVE.W 4(A4),D0 ; Actual key MOVEM.L (SP)+,D1-D2/A0-A4 ; Restore registers RTS EVENTS_BUFF: DS.B 16 DC.B "WAIT_KEY",0,0 EVEN GLOBAL WAIT_KEY
From Eddie's File menu select `Save as...', and name it `WaitKey.S
Step 3 : Creating The Function
Launch PowerFantasm, from the File menu select `Set standalone file...'
- a standard file dialog window open. Navigate to the file you created in
step 3 (`WaitKey.S') and select it then click OK. Next select `Output linkable
file' from the File menu - if it has a tick beside it you're golden. Finally,
select `Assemble' from the Standalone menu.
This creates an object or (more correctly) a link file. A link file is simply
a pre-assembled code module.
BTW
Like me (when I first started using PowerFantasm), you may be asking : "Why
not just copy and paste that section of code into your program?". Well,
you can. However, the whole point of libraries is to make often used functions
easy to use, to make your code a lot more readable and to reduce the probability
of errors in your (main) code.
In this example, this function reduces 27 lines of code to just 2!! Not bad, huh? You could even write a whole program that is made up of library functions (or macros) if you really wanted.
The whole point (for me anyway) is that you can write fairly generic library functions that can be used again and again. Sure, there is a bit of work initially (I won't lie to you), but, after a while you will see this `extra' work really pay off.
Step 4 : Adding The Function
Launch the Librarian and open the library you created in step 1 (or just
double-click the library from the desktop. With your library open, select
`Add a function' from the Library menu. Navigate to your library function
file - in this case `WaitKey.S', select it and click OK.
One other thing to try. From the File menu select `Output Mac RAM' and
then select `Assemble' from the Stand alone menu. PowerFantasm will run
it in real time.
First it will assemble it and display `Press any key to begin execution'
- so press a key, the display changes to `Running...'. Nothing appears to
be happening right?
Well something is happening, it's waiting for you to press a key!
Okay press a key (any key or click the mouse button) and it stops running.
The message `Finished - good assembly' is displayed.
Final Observations (and other Stuff)
Before I continue : I must be honest, both Macs I use have 8MB of RAM (or
more) - so I am able to keep PowerFantasm, Eddie and the Librarian open
at the same time. I highly recommend (if you have the RAM) this approach
- it makes the whole process MUCH easier.
Okay, do you remember the piece I put together on Projects? (Brynley's previous article - Ed.) If you don't, take a minute to at least look at the diagram.
By creating a folder to hold your programs libraries you can save all your libraries and source code in that one folder. Not a major bonus I suppose, but combine that with the fact that if your paths are set correctly, you can very quickly and easily assemble linkable files with next to no extra effort and WITHOUT mucking up your current Project file .
Heres how:
What you can do, after setting up your paths and Project file is to select
`Output linkable file' from the File menu. Why? Simple, you can switch to
Eddie write your library function, switch to PowerFantasm to assemble it,
switch to the Librarian to add the function to your library and then test
the function in your program by using the Build command.
You see Assemble is dedicated to creating standalones, whereas Build only follows the instructions that live in the Build Control File. To reiterate, PowerFantasm lets you work in two `modes' at once without any hassle.
Believe me this is EASIER than it sounds. A very efficient way of working.
Like I keep saying, this stuff is not particularly complex. However, if there is one thing I know for sure, we only use 10 to 20% of what we have available. Whether it be our brains, our minds or our computers.
If the above sounds a bit patronising and too simple, I am afraid I can't apologise. The above `discovery' saved me a lot of aggravation.
Enough from me. Till next time...
Copyright Lightsoft 1996.