HIPPOSOUND
New XBIOS for Haba Hippo-C
by PATRICK BASS, Antic ST Program EditorAntic 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
WHAT'S XBIOS?
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 DEMO
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.
LINK TOGETHER
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.
BUILDING RANDOM
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.
GIACCESS
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.
DEMO TAKE-APART
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.
WRAP-UP
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