Often when writing S*BASIC programs, it is desirable or necessary to use machine code commands. This to speed up certain things (eg SORT), or to reduce the size or complexity of a program (eg EDLIN), or simply because the action you require cannot be done in S*BASIC (eg RPT). For this you require a toolkit.
(In the unlikely event you didnt already know: A toolkit is a collection of machine code functions and procedures that can be loaded into the S*BASIC interpreter, and/or compiled in with your program, and act as if they are part of the S*BASIC language.)
You then either have to produce the necessary assembler code yourself, or find some toolkit(s) you can use. If you simply use an off-the-shelf general purpose toolkit, there is often a lot of extra, unnecessary baggage. Perhaps you only need one or two commands from each of a number different large-ish toolkits! That is wasteful, as lots of code may be replicated in the various toolkits, and you get all those other function you dont need. There are also limits on the number of toolkits (but not commands) that may be included with your compiler.
You will notice that many of the toolkits presented here only contain one or a few commands/keywords. That is because they follow a certain pattern: They are designed to be easy to merge into larger, bespoke toolkits. That way you can build toolkits that only contain the commands you need for a specific purpose. The more commands you combine, the more compact the code, relatively speaking, as common routines are shared between all the commands in the same toolkit.
Other toolkits here contain a larger number of related commands. In those cases it may be possible to strip away any commands, with their associated code, that you dont need. In some cases it wont make much sense as the bulk of the code is shared or intertwined. It is a little more complicated to strip out unwanted commands, as this requires some investigation into how the toolkit was put together. However, if in doubt: Try it out!
No prior knowledge of assembler programming is required to build these toolkits, but if you havent used an assembler before, there is a little work to set it all up. Just jump to the section that represents your starting point and follow the instructions from there.
If you are already set up for assembler programming, these are the steps you need to take to create your own toolkit with my toolkit source files:
DEV_USE 4, "win1_asm_knw_")
Note: My linker/make files are written for QMake, so if you use a different Make, you may need to create your own version of these - or get QMake! The assembler sources follow the Qmac conventions.
What you need to assemble a toolkit:
To use the source files here with a minimum fuss, you need to use the same programs I used to make them, otherwise you will probably need to modify individual files to suit your setup. The simplest setup is to just use QPC2 or SMSQmulator. But you dont have to, of course. If you do, and are new to either of these systems, you could do worse than try out one of the distros. QPC2 has its own mini-distro containing most of the basic environment you need, including tools, games, etc. More elabourate environments can be had with QLE and Black Phoenix. QLE comes complete with both the QPC2 and SMSQmulator emulators, while Black Phoenix requires that you get your choice of emulator first and then fire it up with the Black Phoenix virtual hard disk.
Most of my toolkits need the key files from the SMSQ/E sources, so that is the next port of call: SMSQ/E Sources can be found here. Download the variant that suits you best, ie the QXL.WIN container file or the zip variety. You will need to attach it to your system via the traditional DEV8_ device. DEV is part of SMSQ/E these days. If you dont have, or cant run, SMSQ/E on your system, then youll need to download DEV (dev205.zip) as a separate toolkit from Dr Dilwyn's. (Or you may prefer Phil Borman's SUB device, available from the same place. Just remember to rename the device to DEV.) Luckily the SMSQ/E sources also include the Qmac assembler and linker (in the extras_exe_ directory), so no need to look elsewhere for those.
Note: You dont need to download the complete SMSQ/E sources if you dont want to; just the keys and mac directories and, if you want the Qmac assembler and linker, the extras directory.
For practical reasons, I prefer the QMake make program over any other, but you may be able to manage with the one included with the SMSQ/E sources (or the C68 variant). QMake requires the Pointer Environment and Qmenu, so if that doesnt suit, youll have to make do with one of the others. Youll also need MenuConfig to configure QMake. MenuConfig is included in all the distros, or you can find it at Dilwyn's. Any editor that will edit pure text files may be used. QD is the the most comfortable text editor for the pointer environment. Youll find it in some of the distros mentioned - or get it here.
From here on I assume you are using either QPC2 or SMSQmulator - and if not, that you know what youre doing ;o) Youll have configured QMake to find your chosen assembler and linker, and youll have your favourite text editor ready to hand to create and edit the files you need.
Download the toolkits containing the commands that interest you, plus the library file, LIBxx.zip (required!) and unzip them into some container directory. Eg, if you keep your assembler source files in win1_asm_, create a new sub directory knw so you end up with win1_asm_knw_ You shouldnt go much deeper than that, as the toolkits may have sub directories (and QMake creates intermediary files with an extra 8-9 characters - a flaw, to my mind.) So if you downloaded IOBxx.zip, SCRXYxx.zip, and the library file, and unzipped them to win1_asm_knw_ you should end up with:
The SMSQ/E source files need a device of their own, unless youve only downloaded the key files. This cannot be a DOS/NFA device on Windows, as the sources contain some filenames considered illegal under Windows, so its best to keep them in their own partition or virtual harddisk (eg a "QXL.WIN" file). That way you neednt relocate the assembler and linker either. Now, this is where DEV comes in. SMSQ/E source and key files all expect to be located at dev8_ So if you have your SMSQ/E files at win4_, do:
DEV_USE 8, "win4_"
or if you only have the key and mac files and placed them in win1_sms_keys_ and win1_sms_mac_:
DEV_USE 8, "win1_sms_"
And while youre at it do:
DEV_USE 4, "win1_asm_knw_"
for the toolkit source files.
The first thing to do, before trying to edit anything, is to try to re-assemble an existing toolkit or command. For example, try to make the SCRXY toolkit.
Although you set dev4_ to point to the knoware directory, youll find that any programs that read directories, such as QPAC Files, or Qmenu's file selector, cant handle it. Devs are fine for OPENing a file, but not for navigating (or RENAMING, etc). So, using the example directories I gave above, using QMake's file finder locate the SCRXY_link link file in win1_asm_knw_scr_sxy_. Enter that into QMake and press the DO button. It should then assemble the files to produce SCRXY_BIN in win1_asm_knw_scr_sxy_. If something went wrong, go through the steps above again, or check the Troubleshooting section below. (This section may grow as reports flood in..)
For those commands that fit the pattern, all you need to do is build a new keyword file and a link file. For the keyword file, the simplest is to use the macro template. Just take a suitable existing keyword file and give it a new name. It may look something like this:
* S(uper)BASIC proc/function header * * ępjwitte 2oi9+ * All code is my own work except as and where stated * * V0.03 * * Compatible with SMSQ/E and, apart from IOBSUML, QDOS and Minerva * section code include dev8_keys_qlv include dev8_mac_proc lea.l key,a1 move.w sb.inipr,a2 jmp (a2) * key proc_stt proc_end proc_stt proc_def IOBFMUL%,IOBFMUL proc_def IOBFLIN%,IOBFLIN proc_def IOBSMUL%,IOBSMUL proc_def IOBSUML%,IOBSUML proc_end * end
Using information from the original files, edit the header accordingly with any information you find useful for future reference. (Every line of information has to start with a * or a ; The line can contain any text you like, but should not include square brackes, [ ], or you could get into trouble.)
The functional parts are the bits between proc_stt and proc_end. The first proc_stt/proc_end pair is where PROCedures go; the second pair is where FuNctions go. So if you wanted to add the PROCedure SCRXY to your toolkit, and remove IOBSUML%, the proc bit could look like this:
key proc_stt proc_def SCRXY proc_end proc_stt proc_def IOBFMUL%,IOBFMUL proc_def IOBFLIN%,IOBFLIN proc_def IOBSMUL%,IOBSMUL ; proc_def IOBSUML%,IOBSUML proc_end
So how can you tell whether a routine is a procedure or a function? Well, you cant really, without studying the code. However, the clue is where they came from in the original file. SCRXY is a procedure because it came from this file:
.. key proc_stt proc_def SCRXY proc_end proc_stt proc_end * ..
ie a link file with a single PROCedure.. and because I said so somewhere in the description.
The other thing to note is the following arrangement:
The first IOBFMUL% will be the actual name of the keyword, while the second bit is a reference to the label in the code. If the name and the label are identical (apart from the letter case), then there is no need to specify different names. Thus the label for SCRXY is the same as the name. That means you can use different keyword names to the ones I have used by simply changing them, whilst leaving the label unchanged:
SCRXY will now be called SCRSIZE. Just dont change the labels or the routine wont be able to find its code!
To sum up this first bit: In order to create a toolkit with the commands mentioned, we need to create a new key file. In this example we'll call it dev4_MyKey_asm (The _asm extension is required.) It looks something like this:
* MyTool * Bespoke toolkit for my super-duper program * based on code from ępjwitte 2oi9+ * ; V1.00, First try ; ; Compatible with SMSQ/E, QDOS and Minerva section code include dev8_keys_qlv include dev8_mac_proc lea.l key,a1 move.w sb.inipr,a2 jmp (a2) * key proc_stt proc_def SCRSIZE,SCRXY proc_end proc_stt proc_def FMUL%,IOBFMUL proc_def FLIN%,IOBFLIN ; proc_def SMUL%,IOBSMUL commented out as we dont ; proc_def IOBSUML%,IOBSUML ..want these proc_end * end
This now is the key file for the now renamed PROCedure SCRSIZE and the FuNctions FMUL% and FLIN%. Yes?
Note: In this case, when excluding IOBSMUL% and co, it will also be possible to easily remove some of their associated code, because that code is in a separate file (see further on). This wont always be possible in toolkits with many related commands.
Just a little bit left to do, namely to fiddle the link file. Lets start with the IOB toolkit's link file, IOB_link, and copy it to a new name, such as dev4_MyTool_link:
* IOB toolkit * V0.04, pjw, February 27th 2018 * filetype 0 * dir dev4_ program io_iob_IOB_bin * input io_iob_IOBKey_rel * input io_iob_IOBFMUL_rel input io_iob_IOBSMUL_rel input io_iob_common_rel * library lib_uti_sbu_lib
.. and here is the SCRXY_link link file:
* Qmake link file for SCRXY * filetype 0 * dir dev4_ program scr_sxy_Scrxy_bin * * Keyword definitions input scr_sxy_ScrKey_rel input scr_sxy_SCRXY_rel * * library library lib_uti_sbu_lib
All we need to do is replace the keyword file with the new one just made, and add any unique files from Scrxy_link into the new link file MyTool_link, thus:
* My Super Toolkit, MyTool, based on * IOB, V0.04, pjw, February 27th 2018, and * SXY, V0.01, pjw * V0.01, by me, Jan 2030 * filetype 0 * dir dev4_ * New program name: program MyTool_bin * Replace key file with new one: input MyKey_rel * Keep the IOBFMUL/FLIN stuff: input io_iob_IOBFMUL_rel * Remove code for unwanted commands: * input io_iob_IOBSMUL_rel * Still need this one: input io_iob_common_rel * Add the additional command we wanted: input scr_sxy_SCRXY_rel * AOB library lib_uti_sbu_lib
Note: All _asm files need the extension _rel (=> relocatable object files) in the Make/Link file.) The file lib_uti_sbu_lib was the same for both files, so no need to add it again. (However, see below).
How do we know it was ok to remove IOBSMUL_rel from the mix? Well, the clue is in the name (and if more certainty is needed, in the labels the file contains). Since we didnt want IOBSMUL and IOBSUML it was safe to assume that the code servicing those labels could be excluded. If that was a mistake, then we'd get an error message somewhere, and would have to un-comment the file in the Make file. No harm done. If we only wanted to exclude IOBSUML, it being the odd man out because it is only SMSQ/E-compatible, then we'd still have to include the file IOBSMUL because the code in that file services both those labels.
If you are using QMake, fire it up and enter the filename dev4_MyTool_link (or locate win1_asm_knw_MyTool_link) and press DO. What is supposed to happen is that QMake directs Qmac to assemble any _asm source files that have not already been assembled and convert them into _rel object files. QMake then instructs Qlink, the linker, to link the files together, satisfying any unresolved references (missing common sub routines) by extracting them from the library, and finally, outputting MyTool_bin into dev4_, followed by an reassuring, friendly, beep to confirm: Job well done!
However, youre a pretty lucky sort of fellow if this happens first time you ever try this ;o) So much can go wrong, and as Murphy says: If anything can go wrong it most likely will! So before we go into troubleshooting territory, the first thing to do is go through all the steps again and check them off the list.
Before you get here, you will have checked any error messages against the relevant documentation for the program that produced the error.
Also make sure you have the latest Library files.
The next thing to do might be to check all locations. If you do a DIR dev8_ can you see the keys_ and mac_ directories? and do they contain all the SMSQ/E files that belong there? DIR dev4_ too, and make sure the directories you expect, including lib_, are there. Are the assembler and linker in the locations (Q)Make expects?
If you use different programs to assemble, link or make than those I used, you may have to check that our formats and syntax are compatible. Some assemblers need include files quoted, eg
Qmac doesnt, so I dont use quotes. Not all linkers/make programs understand the dir directive (QLink on its own doesnt, but QMake does). dir creates a common default root, like DATAD$, for all subsequent input files that are not preceded by a valid, full path name. If your Make or linker doesnt support it, simply prepend dev4_ to every input and library name in the link file and remove the dir directive. filetype is another directive not understood by all. Just remove it, or replace it with the corresponding function in your linker/make program. filetype 0 just makes that the toolkit files dont end up getting the EXECutable flag.
A mistake I sometimes make is forgetting to change the input file extensions in the linker file from _asm to _rel, so check
input dir_name_asm ->
You cant use decorative spaces as freely in assembler as in S*BASIC, so ensure you havent inserted spaces or illegal characters:
.. proc_stt proc_def FMUL%, IOBFMUL <- illegal space! proc_def IOBFLIN% <- labels cannot contain % etc! ..
Sometimes QMake throws the error Not Found, without stating what it cant find. That often refers to library modules that reference another module in the same or a previous library: Simply add another input for the library file:
.. library lib_uti_sbu_lib library lib_uti_sbu_lib
QMake and Qlink also throw other strange errors at times, without it being clear what they are. Turn on the MAP function in QMake (or check out the debugging command line options for your linker). Check any debugging files found after assembly. They may be called <filename>_ERR, or <toolkit>_MAP.
While I can not help with any general problems with emulators, distros, assemblers, linkers, etc, if you have any problems specifically with my toolkits, Id like to hear from you, and will try my best to solve the problem, fix bugs, etc, as soon as possible.
pjwitte at googlemail dot c0m