New XBIOS for Haba Hippo-Cby PATRICK BASS, Antic ST Program Editor
Antic has begun receiving letters from readers who want to
know why they can't get our C program listings to work on their Haba
Hippo-C. Most of the reasons were addressed in our review of the product
last month. There are two main problems: No floating point package and
no XBIOS link file. We can't do much about the first, but we can offer
some XBIOS linkage code. The following article provides Hippo-C owners
with two XBIOS calls which they can assemble and link with their C programs.
Antic has also uploaded a custom-designed Hippo-C XBIOS link file
in the Utilities Library of SIG/Atari 16-Bit Forum on CompuServe. Instructions
for using this link file will be found in the ST Section of ANTIC ONLINE.
Because of further incompatability problems, however you still won't be able to type in and run our previous listings-which were written in developers' Alcyon C- under Hippo-C. But we're providing a program here that will demonstrate how to use the new XBIOS calls in this article. We might add that the XBIOS source listing here will not work with Alcyon C because, among other things, Hippo-C passes all parameter data as longwords. Hopefully, Haba will soon provide an update to their C which includes floating point, and a bit more compatibility with Alcyon C. - ANTIC ED
In the realm of CP/M 68K the acronymn "BIOS" stands for "Basic Input/Output System." And in the Atari 520ST the term "XBIOS" is a shorthand way of saying "eXtended BIOS". Extended BIOS routines are designed to handle machine-specific tasks for the Atari 520ST-such as changing the screen location, setting the color palette, or accessing the MIDI port.
There are around 30 of these routines which can be found on a binary link file in the Developers' Toolkit, available from the Atari Corp. for $300. This toolkit, which was developed by Digital Research, Inc., also includes Alcyon C.
But with a little information and some 68000 machine language savvy, you can write your own. Listing 1 is machine language source code for the two XBIOS calls, Random() and Giaccess(). The first routine returns a random number, and the second accesses the AY-3-8910 sound chip.
The XBIOS bindings here are written in 68000 assembly language as implemented by Hippo-C. If you own Hippo-C, then you already have the 68000 assembler that will construct this file.
Examine Listing 1. This is 68000 assembly source code, and may be typed in using the Hippo-C text editor. Type it in exactly as shown and save it to disk under the name: XBIOS.S.
Now back at the "A:" prompt, type: asm xbios.s [RETURN]. Hippo-C will quickly assemble this source code to a file called XBIOS.O inside your USR folder. This is your XBIOS link file. You may now use this on any future Hippo-C programs that need Random() and Giaccess(), such as Listing 2.
Listing 2 demonstrates the use of both XBIOS routines by simply opening a virtual workstation, sounding 100 random pitched notes, and then exiting back to the desktop. (For a detailed map of the registers inside the AY3-8910 sound chip, see the November, 1985 Antic.)
Type in Listing 2 exactly as shown using the Hippo-C editor and save it to disk under the name HSOUND.C. Leave the editor, and from the "A:" prompt type c hsound [RETURN] without the "c" extender. Hippo-C will compile, and then assemble, your C source code into a file called HSOUND.O within your USR folder.
To properly connect, or "link," your XBIOS file to Listing 2, from the "A:" prompt type: 1d-S hsound.o xbios.o [RETURN]. (Be sure to use a capital S.) When the "A:" prompt reappears, you should find your finished program, A.OUT which may be renamed and run from the Desktop.
LISTING 1 TAKE-APART
Before rushing into a run of the program, let's take a closer look at our two listings, beginning with Listing 1.
At the top is a short block of remarks. The first non-remark line is .text, which directs the assembler to assemble the following code into the text segment instead of the initialized and non-initialized data blocks.
In the "Global Communications Section," we establish common labels which will be called from outside this program. Since we need a way to tell other programs at link time that we have two routines available for use, we use the assembler directive .global, which treats the labels _Random and _Giaccess as being available globally- or from outside as well as inside this section of code.
The following subroutine teaches the 520ST how to return a random 24-bit number. The subroutine which actually figures the random number is already in place within TOS, and is known as TRAP #14, opcode #17.
TRAPs in the 68000 are like the CIO routine in the 8-bit Atari computers. You load an opcode (command) number and jump through a common vector to perform different tasks. Except the 68000 has 16 different TRAP vectors with TRAP #14 being the trapdoor into Atari XBIOS.
The first line is the subroutine label _Random:. (The colon is a programming convention to indicate this is a label.)
Next is the link statement which safely stores the current value of address register #6 (a6), then lets us use a6 as our own special stack pointer. Our temporary stack has a reserved length of two bytes. (Note: There's no similarity between this opcode "link" and the "link" in linkfiles.)
The next line down will move a .word (two bytes) "immediately" (# ) the value 17 decimal (the XBIOS opcode number for Random), to wherever our stack pointer (sp) points. Remember, we reserved those two stack bytes in our previous line.
Next, jump through trap #14 into Atari XBIOS. When finished, we return to the next program line and our random number can be found in data register zero (d0).
unik a6 will erase the use of our local stack and restore the previously saved value for address register six (a6). Since we're finished, we rts (Return from Subroutine) back to the calling program.
Now, for our second XBIOS routine _Giaccess. Again, we use address register six (a6) as our local stack, this time with 12 bytes reserved on it.
The first of the next three move statements moves the passed register number onto the top of the stack. The second move places the passed data value onto the next available location on the stack. And the last will push the Giaccess opcode number (28) onto the next available location on the stack.
We now call TRAP #14. Atari XBIOS will read/write the AY-3-8910 chip as we desire and then return to unik a6, after which we rts-return to the caller.
Looking at Listing 2, which is written in C, we first see a group of comments bracketed by / * and * /, Following this, we declare our variables, initialize our constants, and dimension our arrays.
Right below that, in the "External Communications" section, we tell C to be on the lookout during link time for previously defined labels called _Random and _ Giaccess. The linker will supply our program with the values associated with these labels-the final addresses of Random() and Giaccess().
Now we get to main(), the body of the program. The top four lines initialize the GEM application as we've seen in previous Antic listings.
The next three lines demonstrate how to write to and read from the AY3-8910 chip. (For complete details of this chip, see ST Sound in Antic, November 1985.)
The Giaccess() call takes the form: value = Giaccess (data, register), where the value of the register is returned if nothing is added to the desired register number, and data is written to register if the desired register number has 128 added to it.
The first Giaccess() call writes the volume for channel A. The second call saves a copy of register #7 before modifying it. This register controls not only which voices make noise, but also the data direction of two parallel ports the ST uses to control the disk drives. We save this value in port_state so we can later control our drives. The last line in the trio enables voice A to make a pure tone.
Now, we create a For loop that will plug 100 random numbers into the note register of voice A. Inside the loop, two random numbers are placed in x_note and y_note, which represent the 12 bits of voice A's range. Net result?-a random beep or boop. The last line in the loop is a nested delay loop which waits a short while so we can hear the note just selected.
The Random() call does not take parameters. It will return a 24-bit random number. Because the pitch register is a split register consisting of a 8-bit low and 4-bit high, we are masking our two random numbers accordingly.
After 100 loops, we drop to the next Giaccess() call that shuts the playing volume off, restores the port_ enable register-remember, it controls two parallel ports-then closes our workstation and performs an application exit to the desktop.
Still with me? Here we have shown how to build small extensions to Hippo-C that should be helpful in two of the most basic computer game areas, sound generation and random numbers. The idea here is to show how to write a "helper" subroutine in 68000 machine language and call it from Hippo-C.
P.S.-If you wish, you may add the Midiws() XBIOS source code from this issue's MIDI article to this listing so that your resultant link file contains all three XBIOS calls.
Listing 1 XBIOS.S
Listing 2 HSOUND.C