It’s high time we built something, right? Well let’s build something that is certainly for the Amiga, but doesn’t include hundreds of lines of code… Here is some code which we’ll describe later. For fun see if you can guess what it does before reading the description. I’ve actually been using this newly written code as a form of simple “test case” for the various environments I’ve built and re-built over the last few months when preparing this series of articles.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <dos/dosextens.h> extern struct DosLibrary *DOSBase; void reportstate (char *when) { LONG flags = DOSBase->dl_Root->rn_Flags; if (flags & RNF_WILDSTAR) printf ("* %s on\n", when); else printf ("* %s off\n", when); } int main (int argc, char *argv[]) { if (argc != 2) reportstate ("is"); else { reportstate ("was"); if (strcmp (argv[1], "on") == 0) DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR; if (strcmp (argv[1], "off") == 0) DOSBase->dl_Root->rn_Flags &= ~RNF_WILDSTAR; reportstate ("is now"); } return 0; }
One thing to be aware of is that the compiler we have installed has a fairly limited C library, so you will note we use “strcmp” and test for “on” and “off” which would fail for “ON” or “On” or “oN”. The library sadly does not include a “strcasecmp” function. However this is a demonstration piece, so we’ll accept this limitation.
Let’s go through this a bit… First of all let’s talk about libraries. The Amiga OS is a bit like a “micro-kernel” based system with a small “core” and lots of additional modules. The Amiga’s core is “exec.library”, and one of the additional modules is “dos.library” which is basically speaking the disk operating system providing access to files and so on. Because basically every program uses these libraries the normal “startup” for C programs “opens” these libraries, or more precisely “locates” the exec library and with that “opens” the dos library. These are usually ROM based on the Amiga except in very rare circumstances.
We need to “talk” to the AmigaDOS so we need information about it and in this case a “pointer” to the library that the C startup code has opened.
#include <dos/dosextens.h> extern struct DosLibrary *DOSBase;
Starting with the “2.0” operating system there has been a “hidden” flag to enable the use of the asterisk (*) as the wildcard, instead of the original Amiga wildcard of “#?” quite literally translating to any number of any character. This is stored in the “root node” of the DOS library. If we want to “report” on the state we can fetch and test it as follows.
LONG flags = DOSBase->dl_Root->rn_Flags; if (flags & RNF_WILDSTAR)
Due to differences in compilers and platforms, not least because the original Amiga OS was “cross-compiled” the Amiga OS defines its own variable types with “LONG” being a 32-bit integer. The DOSBase pointer set by the C startup code points to the DOS library data including a pointer to the “root node” structure and from the root node you can get to some flags. These structures are in the “dos/dosextens.h” file from the NDK. The flag we want is termed “WILDSTAR” which is also defined in that include file. Amiga flags tend to be defined “<Struct>B_<Name>” for bit position and “<Struct>F_<Name>” for bit mask, so “RNF_WILDSTAR” is the bit mask of the “WILDSTAR” bit in the “root node”. Try searching for the definitions in the include file (probably easiest in the “XFER” area on your chosen host).
The easiest and safest way to control flags is probably using bitwise assignment operators, so to turn the flag on you can OR the flag mask.
DOSBase->dl_Root->rn_Flags |= RNF_WILDSTAR;
To turn the flag off you can AND the inverted flag mask.
DOSBase->dl_Root->Flags &= ~RNF_WILDSTAR;
Everything else is just basic C code.
For working in the Amiga emulator with the Amiga set for an American keyboard let’s recap on some “special” characters and their locations.
# - shift-3 " - two keys right of L, shifted \ - three keys right of L, unshifted | - three keys right of L, shifted ~ - one key left of 1, shifted
Most other symbols for programming will probably match your keyboard. For future reference the ‘@’ symbol is shift-2.
Make a file called “sw.c” at the root level of the “Work” drive (let’s be untidy for now) and enter the code listed at the start of this post. I personally used “Vim” but you may find “Redit” easier. Then we can compile the program. If the “vc” command returns an error, check the code carefully against the listing.
cd Work: Redit sw.c vc sw.c -o sw sw
When the Amiga boots the flag will be off. What did the program report?
Have you used C-Shell (prior post) since you booted the emulated Amiga?
It turns out that C-Shell will by default turn the flag on when it starts but it never turns it off, so even if you “quit” the flag will be left switched on. C-Shell will also turn the flag on at other times. If you are using C-Shell type “quit” before the following test to demonstrate the effect.
sw off copy *.c t: copy #?.c t: sw on copy *.c t: copy #?.c t:
With the setting “off” trying to copy “*.c” will generate an error.
Can't open *.c for input - object not found
The second copy command is the traditional/original AmigaDOS wildcard and will copy our source file to the Amiga’s “temp” folder.
When the setting is switched on however BOTH commands will work. The setting doesn’t CHANGE the wildcard, it just adds a new one.
There are scenarios where the star wildcard will not work, but it will work in several places.
To recap what we have covered… We have pulled in an operating system include file and we pulled in a “library base pointer”. We didn’t need to “open” the library because ‘C’ startup code did it for us. We went into a publicly defined operating system structure to fetch and report on a flag value, and also switched the flag on and off. We tested and witnessed the effect of the flag.
When I compiled the code today the result was a 7,880 byte executable, which if you recall has to have the on/off switch provided in lowercase. Still seems pretty good compared to modern systems, right?. I wrote something to do this in November 1992 in assembly language, using another AmigaDOS call called “ReadArgs” which provides support for command line help as well as being case-insensitive for the on/off switches and the result was an 836 byte executable.
It’s feels about time to dig into some T81T archives…