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.