                   Blitz2 Library Developers Documents
                             September 1994
                      Mark Sibly and Simon Armstrong



INTRODUCTIONS

The following is a collection of articles, docs and so forth for those
wanting to develop command libraries for Blitz2. Only those experienced
in the ways of assembly programming will be interested.


COPYRIGHT NOTICE

To help those wanting to develop libraries a large number of source codes
have been included in this archive. All code include is copyright and
hence should not be duplicated in other files without the author's
express permission. Authors can be contacted via the address given in
the documentation for each library published in BUM7.

Acid Software can be contacted either via email: at acid@iconz.co.nz or
via fax on +649 358 1658.


TOOLS OF THE TRADE

Before starting on your own libraries several programs and files will
need to be setup in their correct position. First the blitzlibs: volume
which includes the userlibs, amigalibs, basic and system directories
should be installed on harddisk with an "ASSIGN BLITZLIBS: pathname"
added to the your system's startup-sequence.

Along with the 4 directories in blitzlibs: (do NOT add any others)
copy the res files included in this archive, in particular make
sure the file blitzlibs:libmacs.res is able to be found by Blitz2.

You will also want to create executable versions of the libsdev tools,
the src has been included in the toolssrc directory of this archive.
It is probably easiest to compile them to your c: directory.


OVERVIEW

Blitz2 has an expandable command set. When you startup Blitz2 it attempts
to load the command set from the file Blitz2:DefLibs. If it cannot find
this file it will load the command set from the Blitzlibs: directories.

Users are able to create new command libraries and add them to the
userlibs directory of blitzlibs:. While developing a library remove
the deflibs file from the Blitz2: drawer so that Blitz will always
load it's commands from the BlitzLibs: volume. You can also override
the DefLibs commands by select ReLoadLibs from the compiler menu.

After creating a new .obj file in your blitzlibs:userlibs drawer you
can test your library select ReloadLibs and create a test program to
use your new commands. If Blitz2 crashes with an "Out Of Memory" or
some such error during loading of libs, you have obviously created
an illegal library file and will have to remove it from Blitzlibs:userlibs
before restarting Blitz2.

Other things to make sure of when creating library .obj files is to
never have runtime errors enabled and never include any BASIC tokens
(the END statement in particular), both these will create illegal
library files.

Once your library is complete you can use the makedeflibs command to
create a new Blitz2:DefLibs file so you can return to the fast loading
Blitz2 you once new (Blitz2 is much quicker at loading DefLibs than
scanning the entire BlitzLibs: volume).


CONVERTING STANDARD AMIGA LIBRARIES...

If you just wish to access an unsupported standard amiga library (such
as those that hang out in your libs: drawer) you will need to convert
it's corresponding .fd file. You will notice the .fd file contains
parameter and syntax information for all the commands in the .library
file. By running the fdconvert tool, you can add a corresponding
Blitz library in the BlitzLibs:AmigaLibs drawer which will let you
access these commands from Blitz2. Make sure the .fd library specifies
the name of the actual library in the top line (same as DOS3 standard
.fd files).

The fdconvert program should assign a suitable library number for your
new amigalib. Check the libnums.bb file in the ressrc file for
what library number assigns have been made for amigalibs upto
now (first available should be #217).

After running fdconvert either create a new deflibs file with the
makedeflibs tools or use ReloadLibs in the Compiler menu of Blitz2.
All the commands that were listed in the fd file should now be
part of Blitz2, the only difference is that they are all succeeded
by an underscore character to avoid clashes with Blitz2 tokens.



---------------------------------------------------------------------------------
      Text file taken from BUM7's readme directory by Simon Armstrong
---------------------------------------------------------------------------------


Notes for Library Developers

Well, I've been a bit bamboozled by all the userlibs that have been
arriving in the mail. The following are a few notes I've jotted down
after spending a lot of time trying to tidy up what you guys have
been sending in.

1. LibNums and general naming conventions.

OK, first up, library numbers. Not a big deal as we are probably
going to get rid of tokenising in Blitz3 so that 1. we don't get
all the clashing that has been going on and 2. users can use what
ever ascii editor they please. However in the mean time (and for
ever more if the Amiga is still out of production by XMas)....

Do NOT use library numbers above 40. Especially do NOT go sticking
your libraries in between Acid ones (ELMORE!!!) we left the odd
numbers for our own expansion not yours! To be generous I have
allocated the following for those that feature on BUM7 and are working
on new libraries:

Elmore - 99 97 95, RI - 63 58 51, Neil - 50 49 48, Romulus- 47 46 45


Secondly, do not use words like len, start and so forth (RI!!!). As
BASIC programmers like to use such words for variables it is a bit
rude to find that someone has gone and called a command after your
favourite variable name (don't don't don't add a command called i!),

To be really snazzy you should try and use the library name (make it
concise) in all your tokens like I have done in the display library,
this makes things a lot easier to read, avoids token clashes (Elmore,
any chance of a tokenclash tool?) and possibly keeps you on the straight
and narrow.


2. Syntax and library content.

Avoid extraneous commands at all costs. If you can use different forms
of the same command DOIT. If the command is the same as using two or
three commands don't bother. Rule of thumb I suppose is add parameters
to make key commands more powerful rather than adding more commands.

If you are just implementing small pieces of machine code to do miscellaneous
jobs don't bother. Just stick the machine code in a statement and publish
the statement. Commands added to Blitz2 should not be the sort that you
can acheive in a few lines of code, they just make Blitz2 a more obese
rather than ultra powerful language.

With the advent of the ASMEXIT command machinecode routines can now
be placed in functions and statements in a stable manner. To use
ASMEXIT do not use UNLK A4 but simply replace any RTS commands
with ASMEXIT, ensure that registers a4-a6 are restored before
ASMEXITting.

If you are adding commands that belong in Acid libraries, please ask me
for the source for that particular library, and add them there, it makes
my job a hell of a lot easier and means with new documentation users will
know about your command cos they are looking in the correct section ot
the manual.


3. A few other pointers...

* OS2/3 specific commands should check the version of exec and exit
  cleanly if too old:

  MOVE.l 4,a0:CMP #36,20(a0):BCS doexit    ;wo older than v36!!!

* Use Blitz2 objects if they are suitable, best place to work out
  how they work is in the source code the acidlibs I have included
  in the libsdev archive. Hmmm, a quick lesson on this follows below.

* always use ALibJSR $c002 and $c003 for allocating and freeing
  memory, never use the exec calls...


4. And please please please...

Prefix the name of you library with your handle or name, those finding
to their horror the source of their libraries published here please
update your own source codes with the changes I've made.

Keep a history file at the top of your library source, it makes keeping
the documentation uptodate so much easier.

Test your commands with bad parameters to make sure your error checking
is cool, save a .test file with your library when you submit it so others
can see how to use your commands, and try and follow the documentation
style that I've been using in BUM7. IE, list all the commands at the
top then describe them one by one.

Keep your .res files in the root of blitzlibs:, reference all resident
files in compiler options as blitzlibs:filename.res and use
blitzlibs:userlibs as the path when creating object files. Getting a
bit picky here I think. Oh DO take notice of the new keyboard shortcuts
in the compiler menu.


5. And very importantly...

Make sure you return A4 how you found it, it is the local variable
base and if you stuff it you will not be able to use your commands
inside functions and procedures (yes I know I am guilty of this
often).

Keep your library .obj files as small as possible. If you need a hunk
of memory allocate it in the init routine, DON'T USE ds.l big. If you
have a look up table try and generate it from allocated memory during
initialisation rather than INCBIN the thing, DefLibs is too bloody
big as it is, don't push it! Anything over 4K is no go unless it is
major cool.

Use moveq whenever possible. It is fast and sign extends to a
long word. Use pc relative adressing as much as possible as Blitz2
does not optimise this. Use addq and subq also whenever possible.

Anyway, thanks for everyone who has been adding commands, please don't
take the above personally just trying to keep things tidy...

Blitz2 Library Objects.


Yes, bloody wonderful things. OK, say your library is based around a
particular object or structure, hopefully something useful that will
make Blitz2 programmers want to give you their girlfriends...

First up I define a NewType similar to the other Blitz2 objects as listed
in an appendix of the Blitz2 manual, and define a macro to make my assembly
code much more readable:

Macro s
  {SizeOf.sound\`1}(a3)
End Macro

NEWTYPE .sound
  data.l
  size.l
  period.w
  volume.w
  priority.w
  etc etc
End NEWTYPE

Of course I call my library acidsoundlib so it doesn't get mixed up with
everyone else's sound libraries, assign it a number (see above) and define
the name of my sound object in the dumtoke, This allows the programmer to
use the free object, addr object() etc. on my object.

#acidsoundlib=40                      ;library number at top as constant

!libheader {#acidsoundlib,init,1,0,0} ;header with init routine if needed

!dumtoke{"Sound","",_toke}            ;wo clash, only example ok?

!astatement
!args {#word,#long,#word}
!libs {#acidsoundlib,$1380}
!subs {_initsound,0,0}
!name {"InitSound","Sound#,length,flags"}

init:!nullsub {_initlib,0,0}

_load:!nullsub{0,0,0}
_save:!nullsub{0,0,0}
_use:!nullsub{0,0,0}
_free:!nullsub{0,0,0}

!libfin{_toke,_load,_save,_use,_free,4,5}

OK, we don't worry about the nullsubs this week. the last two numbers in the
libfin macro define the default number of objects (before the user increases
them via the compiler options) and the size of the object which is 2^n so
Blitz2 can do a shift to calculate the location of the object any parameter
is referencing. The 5 means our object can take up to 32 bytes.

Hmmm, the !libs macro has the number $1380. There are some macros in libmacs for
this but I always forget them. The high byte says which address register you
want to point to the object, the low byte defines which parameter to use:

#a0=$1000:#a1=$1100:#a2=$1200:#a3=$1300:#a4=$1400:#a5=$1500:#a6=$1600
#p0=$80:#p1=$81:#p2=$82:#p3=$83:#p4=$85:#p5=$85

So if I want the adress register a3 to point to the object# defined by the
first parameter I use the code #a3+#p0 = $1380

If I had a copy sound command that needed source in a2 and destination in
a3 I'd use the following setup:

!astatement
!args {#word,#word}
!libs {#acidsoundlib,$1280,#acidsoundlib,$1381}
!subs {_copysound,0,0}
!name {"CopySound","SrcSound#,DestSound#"}

And, gosh it's exciting... yes a2 and a3 will be preloaded all ready to go
at the start of your routine. Use #word in !args for all parameters that
refer to objects.

OK, thats about it, oh the macro and newtype stuff, basically if you always
pass the object number in say a3 set up the macro as I have done and whenever
you want to reference a field in the object you can use it's name e.g.

move.l !s{size},d1:move.l !s{data},d2

which is the same as

move.l 4(a3),d1:move.l 0(a3),d2

Hmmm, other things:


1. Objects are always initialised with zero's on program startup

2. The free subroutine if you provide one will be called for all
   objects on program exit.

3. See banklib source for basic memory management.

4. Use other libraries objects, but always check if they are initialised.


---------------------------------------------------------------------------------
    Following republished from AmigaDownUnder article by Mark Sibly
---------------------------------------------------------------------------------


                    HOW TO WRITE BLITZ BASIC 2 LIBRARIES
                    ************************************

  The Blitz 2 compiler is heavily library orientated. What this means is
that many of the routines and functions used by the compiler are not actually
stored in the compiler itself, but in completely separate library files.

  This set up allows new commands and features to be easily added to the Blitz 2
system, simply by creating a new library file.

  Libraries in Blitz 2 are usually written in Blitz 2 itself, and must be
TOTALLY in machine code.

  Before we get into actually writing a library, let's first have a look at
the basic layout of libraries in Blitz 2.

                        Varieties of Blitz 2 Libraries
                        ******************************

  Blitz 2 makes use of 3 types of libraries - system libraries, Amiga libraries
and command libraries. Let's have a closer look at these:

* System libraries - These libraries are used internally by the Blitz 2
  compiler and include such mundane operations as memory allocation, string
  manipulation and so on. System libraries will only ever be modified by Acid
  software, as they work in connection with Blitz 2 at a very low level.

* Amiga libraries - These libraries allow Blitz 2 programmers access to any
  of the operating system libraries (eg: intuition.library,exec.library).

* Command libraries - These libraries form the bulk of the Blitz 2 system, as
  they contain all the BASIC commands and functions available to Blitz 2
  programmers. All of the Window, Screen, Blitting etc. commands are held in
  command libraries. To add new commands to Blitz 2, a command library should
  be created containing these new commands, and this is just what we'll be
  doing...soon...

                  Where ARE the Blitz 2 Libraries to be found?
                  ********************************************

  When Blitz 2 starts up, it needs to be able to locate all the libraries
available. It does this by first looking for a file called 'Blitz2:Deflibs'
(for 'default libraries'). If this file is not found, Blitz 2 then goes and
looks for a directory called 'Blitzlibs:'. If neither Deflibs or Blitzlibs:
can be found, then Blitz 2 gives up and politely (?) exits.

  If Blitz 2 can find Deflibs, then it uses the contents of Deflibs as it's
libraries. If Blitz 2 can only find Blitzlibs:, it then proceeds to scan any
sub-directories of Blitzlibs:, and uses any files found as it's libraries.
At the moment, there are 4 sub-directories set up within blitzlibs: - 'System',
'Amigalibs', 'Basic' and 'Userlibs'.

  It's worth pointing out here that Deflibs is simply all the separate Blitzlibs:
libraries joined together as one continuous file. This was done to speed up
the library loading process, and to make the whole system more user-friendly.
A program called 'Makedeflibs' can be used to create the Deflibs file from
the individual Blitzlibs: libraries.

                              Getting started
                              ***************

  First, you'll need to unarchive the 'blitzlibs.lha' file into a blitzlibs
directory, and add yet another assign to your startup-sequence (eg: assign
blitzlibs: blitzlibs). Next, get rid of 'Blitz2:deflibs' to prevent Blitz 2
from looking for it instead of blitzlibs:. This can be done simply by moving
Deflibs from the Blitz2: directory to a different directory, or by renaming
it.

  Next, crank up Blitz 2 to make sure everything's still going OK. You should
notice Blitz 2 takes longer to startup, due to it having to load in the
individual library files from blitzlibs:.

                         Writing a Blitz 2 Library
                         *************************

  Before you can go ahead with writing your library, you'll have to first
choose a 'number' for your library. Each library in Blitz 2 has it's own unique
identifying number, so you must make sure the number you choose for your library
does not clash with any other libraries.

  Acid software has decided, in it's infinite wisdom, that any libraries under
development should be given a library number from 10...50. So, you'll probably
choose 10 for your first library, 11 for your second, and so on...

  If you finish a library and are pretty proud of it and feel it would be of
benefit to Blitz users in general, Acid software can be contacted to obtain
a permanent library number.

  One more thing you'll need to write your library is the 'libmacs.res'
resident file. This file contains a set of macros and constants necessary
for writing libraries. If you're not familiar with resident files, refer to
the Blitz 2 User guide section 10-1.

  Libmacs.res can be found in the Blitzlibs: directory, and before starting
work on a library you'll need to load it in via the 'Compiler/Options'
menu.

  OK, so you've got libmacs.res loaded and you've decided upon your library
number. It's now time to get coding!...

  We'll start of with a quick example library that doesn't do all that much
but should give you an idea of what's going on:


;
;examplelib
;
;An example of library writing in Blitz 2
;
;A decidedly useless command to blink your LED on/off
;
;we're going to give our library the number 10...

#mylib=10

;***** First up, a header for the library... *****

!libheader{#mylib,0,0,0,0}

;***** now, the actual commands in the library *****

!astatement
!args{#word}
!libs{#graphicslib,#la6}
!subs{doblink,0,0}
!name{"Blink","number of blinks"}

;That's it!

!libfin

;***** Now comes the code for the library *****

doblink
;
MOVE d0,d2:BEQ 'skip:SUBQ #1,d2
'loop
BCHG #1,$bfe001:JSR -270(a6)    ;call graphics library 'Wait top of frame'
DBF d2,'loop
'skip:RTS

;***** That's all for our library! *****


  Once you've typed this in, save it, then create an executable by the name of
'Blitzlibs:userlibs/examplelib.obj'.

  To test out your library, use the 'Compiler/Reload Libs' menu item. This
will force Blitz 2 to re-load all it's libraries from Blitzlibs:. Following
this, your awesomely useful 'Blink' command should now be available to
Blitz 2...

;
;Test of the new 'Blink' command...
;
Blink 10    ;blink ten frames....
;

  Now, let's go through the examplelib a line at a time:

!libheader{#mylib,0,0,0,0}

  The !libheader macro should always appear at the start of a library.
The libheader macro looks like this:

!libheader{library number,initialize,return,cleanup,runerrs}

  The 'initialize' parameter allows you to specify a routine which gets
executed when a Blitz 2 program is run. Likewise, 'finish' may specify
a clean up routine when the program ends. If either of these is set to 0,
then they are ignored.

  The 'return' parameter allows the library's initialise routine to return
a value, in d0, which other libraries may access. If this parameter is 0,
then this means the libraries initialization returns nothing. If this parameter
is 1, this means the initialization routine returns a value in d0 which other
libraries may access. We'll have a closer look at this when we get to the
!libs bit...

  'Cleanup' is similar to 'initialize', allowing the library to doing any
tidying up when the program ends.

  The 'runerrs' parameter informs Blitz2 of where any runtime error checking
code is located. We'll go into this later as well.

  After the libheader, the library then goes on to specify the actual commands
in the library - in this case, there is only one command...

!astatement
!args{#word}
!libs{#graphicslib,#la6}
!subs{doblink,0,0}
!name{"Blink","number of blinks"}

  The !astatement macro specifies that this command is a statement, as
opposed to a function. In other words, Blink doesn't return any value.

  The !args macro gives the arguement template for our command. In this case,
!args{#word} means that the Blink command takes only 1 parameter - a 16 bit
word. We can specify as many parameters as we want here, and they may be any
of the following types:

#byte
#word
#long
#quick
#float
#string

  Parameters are passed to library routines through the 68000 data registers
D0 through D6 - the first parameter being passed in d0, the second in D1 and so
on. If there are more than 7 parameters, extra parameters get passed on the
stack. Also, string variables are passed through the use of a data register
as a pointer to the string, and the length of the string on the stack. We'll
cover stack usage in more detail a bit later on.

  Onto the !libs macro. This macro allows us to 'grab' data from other
Blitz 2 libraries for use by our command...

!libs{#graphicslib,#la6}

  In this case, we are asking for the 'graphics.library' library base to be
placed in A6 before our blink routine is called. Remember the 'initialise'
and 'return' parameters of the !libheader macro? Well, the Blitz 2 library
'graphicslib' uses these parameters to open the graphics library and return
the library base in d0 for other libraries to use.

  We can also specify multiple libraries using the !libs macro. For example:

!libs{#graphicslib,#la6,#intuitionlib,#ld6}

  Will give us graphics base in a6, and intuition base in d6.

  Now we get to the !subs macro:

!subs{doblink,0,0}

  This simply contains a pointer to the actual code to execute once all
parameters and library values have been placed in appropriate registers.

  The 2 '0' parameters here are used for runtime error checking purposes.
More on this later.

  Finally, we get to name our new command:

!name{"Blink","number of blinks"}

  The !name macro takes at least 2 text parameters. The first gives the
actual name of the command, while the second specifies the 'help' text for
the command. A third parameter may be given allowing a label to be associated
with the text - this is of use when creating Blitz 2 objects (see below).

  Once we've finished specifying the format of our libraries commands, we
use the !libfin macro:

!libfin

  The rest of the program contains the actual machine code to perform the
Blink command.

                                  FUNCTIONS
                                  *********

  Blitz 2 functions are created almost identically to statements, except we use
the !afunction macro instead of !astatement. The !afunction macro must
be supplied with a single parameter indicating what type of result is returned
by the function. Then, it's up to the actual function code to return the
appropriate type of value in D0.
  Let's expand our library to demonstrate writing a function...


;
;examplelib
;
;An example of library writing in Blitz 2
;
;A decidedly useless command to blink your LED on/off
;
;we're going to give our library the number 10...

#mylib=10

;***** First up, a header for the library... *****

!libheader{#mylib,0,0,0,0}

;***** now, the actual commands in the library *****

!astatement
!args{#word}
!libs{#graphicslib,#la6}
!subs{doblink,0,0}
!name{"Blink","number of blinks"}

!afunction{#word}               ;inidcates that this function returns a word.
!args
!libs
!subs{doledstatus,0,0}
!name{"LEDStatus",""}

;That's it!

!libfin

;***** Now comes the code for the library *****

doblink
;
MOVE d0,d2:BEQ 'skip:SUBQ #1,d2
'loop
BCHG #1,$bfe001:JSR -270(a6)    ;call graphics library 'Wait top of frame'
DBF d2,'loop
'skip:RTS

doledstatus
;
BTST #1,$bfe001:SNE d0:EXT d0:RTS

;***** That's all for our library! *****


                   LIBRARY INITIALIZATION AND CLEAN UP
                   ***********************************

  If your library needs to perform some kind of initialization or cleaning up,
the 'initialize' or 'cleanup' parameters of the !libheader macro may be used.
However, instead of simply pointing to some code, these parameters should
point to a !nullsub macro. A WHAT!?!? Well, !nullsub is basically a combination
of the !subs and !libs macros. The first 3 parameters of !nullsub are the same
as those for !subs, while the rest allow you to pickup values from other
libraries similar to the !libs macro. This set up allows you import data from
an external library for use during initialization or cleanup. For example,
let's say you need intuition base to perform your libraries initialization and
cleaning up:

!libheader{#mylib,init,0,cleanup,0}

init
!nullsub{doinit,0,0,#intuitionlib,#la6}

cleanup
!nullsub{docleanup,0,0,#intuitionlib,#la6}

.
.
.

!libfin

doinit      ;actual initialization code...

docleanup   ;clean up code...

  Note that libraries are initialized numerically, from higher numbered
libraries to lower numbered. Therefore, if you have written 2 libraries of
which one requires the returned value from the other, the library supplying
the value should be of a higher library number than the one receiving.
  Also note that the !nullsub macro should appear between the !libheader
and !libfin macros - NOT in the main code.

                                THE STACK
                                *********

  Parameters are normally passed to library routines through data registers
D0 through D6. However, in the case of string variables, or when a command
requires more than 7 parameters, parameters may end up on the stack. To help
in keeping track of stacked parameters, Blitz 2 copies the stack pointer to
address register A2 before anything gets placed on the stack. This allows
you to step through stacked parameters using the -(A2) addressing mode instead
of having to play around with offsets from A7. For example, say you're writing
a command which requires one string parameter. When the commands routine is
called, the address of the string will be in D0, and the strings length will be
on the stack. The routine could then pick up the strings length using:

move.l -(a2),d1

  Note that Blitz 2 Version 1.80 and higher will automatically null terminate
all strings. Earlier versions only null terminate the last string of a
parameter list.
  Also remember that if you're wanting to use A2 in this way, you must not
use A2 in the !libs macro.


                          RUNTIME ERROR CHECKING
                          **********************

  Blitz 2 libraries may also contain runtime error checking code. This code may
be used to check that command (or function) parameters are within a legal range.
Remember, this extra code will only be executed if the 'RUNTIME ERROR CHECKING'
option within the compiler/options menu is enabled.
  Error checking code must always appear at the end of a library. This
allows Blitz 2 to drop this code when runtime error checking is disabled.
  To add error checking to a library, you need to indicate where in the
library the actual error checking code starts. This is done through the
'runerrs' parameter of the '!libheader' macro. Then, it's simply a case of
using the '!subs' macro to indicate any error checking routines that needs to be
called.
  If an error checking routine decides that a parameter is bad, a 'TRAP #0'
should be executed with D0 pointing to an appropriate error message string.
  To demonstrate this, we'll alter our example library to make sure 'Blink' only
allows parameters of 0...100:

;
;examplelib
;
;An example of library writing in Blitz 2
;
;A decidedly useless command to blink your LED on/off
;
;we're going to give our library the number 10...

#mylib=10

;***** First up, a header for the library... *****

!libheader{#mylib,0,0,0,runerrs}

;***** now, the actual commands in the library *****

!astatement
!args{#word}
!libs{#graphicslib,#la6}
!subs{doblink,doblinkcheck,0}
!name{"Blink","number of blinks"}

!afunction{#word}               ;inidcates that this function returns a word.
!args
!libs
!subs{doledstatus,0,0}
!name{"LEDStatus",""}

;That's it!

!libfin

;***** Now comes the code for the library *****

doblink
;
MOVE d0,d2:BEQ 'skip:SUBQ #1,d2
'loop
BCHG #1,$bfe001:JSR -270(a6)    ;call graphics library 'Wait top of frame'
DBF d2,'loop
'skip:RTS

doledstatus
;
BTST #1,$bfe001:SNE d0:EXT d0:RTS

;***** OK, time for runtime error checking code! *****

runerrs

blinkcheck
CMP #101,d0:BCC blinkerror:RTS

blinkerror:MOVE.l #blinkerrortext,d0:TRAP #0

blinkerrortext:DC.b "Number of blinks must be 0...100",0:EVEN

;***** That's all for our library! *****
;

                      WARNING! WARNING! WARNING!
                      **************************

  Any library routines, whether they be statements, functions, runtime error
checks or simply initialization code, MUST preserve address registers A4, A5
and A6. As well, a function MUST ALSO preserve address register A3. Just what
are these registers used for?

A6 : Blitz keeps track of A6 to prevent it having to be unnecessarily
     re-loaded.
A5 : Blitz 2's global variable base.
A4 : Blitz 2's local variable base.
A3 : Blitz uses this to build temporary strings.


                          THAT'S ALL FOLKS
                          ****************

  Hopefully, you'll now have enough information to begin writing your own
libraries. In the next installment of this series, we'll have a closer look
at string variables in Blitz 2, creating Blitz 2 objects and more. In the
interests of keeping this document as self contained as possible, I'll finish
up with the source code to libmacs...

Plesant programming,

Mark Sibly

