|
Vectrex Programming TOC
Sound Playing
Now you know (with a little experimenting on your side) how to draw
vectors, dots and whole objects of vectors. You know how to move them,
how to scale them and give them different brightnesses. All these things
done via a couple of BIOS functions. Now let us go on to something completly
different. Let us enter the universe of sound! To keep one thing clear
in mind, I am no musician, I can't read a single note, and I won't go into
any depths on this subject, I'll tell you what BIOS routines are available,
a bit how to use them - that's all!
A little introduction nonethless befor we start. The soundchip of the
vectrex is a Programmable Sound Generator (short PSG), it's correct name
is AY-3-8912. Appendix D is an extract of the
reference manual of that chip. The vectrex uses the PSG not only for sound
generation, but also for communicating with the outside world. Register
16 of the PSG is connected to the joypad electronic. The PSG itself cannot
be addressed directly, only by sending the correct byte sequences to the
VIA chip. As you might imagine it is cumbersome to program that thing yourself.
The original vectrex programmers thought so too, that is why a whole series
of functions exist that make life easier. There are functions to aquire
joystick positions, button stati, sending bytes and streams of bytes. There
are even functions to play songs and noises. The only sound functions I
used so far are the functions needed to play some notes. These will therefor
be the only (sound) functions I'll explain a little, the other sound related
functions are again left as an exercize for the reader.
Get on with it...
First, let me shock you a little with the available sound functions:
Clear_Sound ($F272)
Do_Sound ($F289)
Do_Sound_x ($F28C)
Init_Music ($F68D)
Init_Music_Buf ($F533)
Init_Music_chk ($F687)
Init_Music_dft ($F692)
Explosion_Snd ($F92E)
Sound_Byte ($F256)
Sound_Byte_x ($F259)
Sound_Byte_raw ($F25B)
Sound_Bytes ($F27D)
Sound_Bytes_x ($F284)
Of the above functions we will look a bit closer only at the following:
Init_Music_Buf ($F533)
Init_Music_chk ($F687)
Do_Sound ($F289)
Of these only the last two are needed to play a piece of music. There is
also a very interesting RAM location, Vec_Music_Flag ($C856), but later
more on that.
Befor we play our first piece of music, again a little (second) introduction.
The BIOS designers really cared about programmers who wanted to play music
which knew nothing about the PSG. They designed routines, which allow us
to create pieces of music as they come to our mind and writing down the
notes like we learn them (or don't :-() in school. The PSG supports 3 voices
at the time, so our music can also be played utilizing three voices. Furthermore
it has the ability to create noises, so we can not only play music, but
can also have some shooting or explosion or the like sounds (snare drums...).
The music playing routines the BIOS provides us with, enables us to
use 64 notes, ranging from G2 to AS7 (S=Sharp). As usual (?) in each octave
we have 12 different notes, look at Appendix F for a list of all notes. If you absolutly hate music and do not even want
any further information, the BIOS has several pieces of music built into
(13 I think), you can use them in your programs for several usages, they
range from simple songs, to some noise and bonus sounds. Look at the Appendix
A other ROM addresses as to where these are located. Actually now that
I think of it, we could start playing one of them, just to show you, how
to set the system up and going, before we move on to how the song structure
looks like.
sound1.asm
This time we have to set up something befor we enter our main loop.
In order for the music routines to work they must be initialized. This
is rather easy, because they are sort of self initializing. All we have
to do is make sure that they know, that a new piece of music is about to
begin. The before mentioned BIOS RAM variable Vec_Music_Flag keeps track
of the current state of music playing routines. Three states are possible,
0 means no music playing. 1 means about to start a new piece of music,
and $80 finally means, that a piece of music is currently playing. Since
we want to start a new piece of music we store a 1 in that location and
with that we are allready done with initializing. We enter the main loop.
Right before we call the Wait_Recal function the sound update routine is
usually called, this routine is called Init_Music_chk ($F687). This routine
checks and updates the state of all PSG shadow registers. These shadow
registers are copies the music routines use in order to easily keep track
of the PSG state. The first time we call the routine it initializes the
shadow registers of the PSG with the first set of notes our piece of music
consists of. It than changes the state from 1 to $80, from 'about to play'
to 'I'm currently playing'. This routine only updates and calculates the
shadow registers, it does not access the PSG. Befor calling the routine
we must ensure two things, first that DP is pointing to $C8, and second
that we put the address of the music we want to play into register U. This
we do. The music we want to play is a piece of BIOS music, here called
(highly unimaginative) music1. This is the all known startup music. After
vector hardware recalibration we call another music routine, Do_Sound ($F289),
this routine looks whether the shadow registers have changed, if so it
copies the changed ones into the PSG chip. In order for that to work correctly
the DP register must be pointing to $D0, having just called the Wait_Recal
routine that is insured. Done. We loop thru that eternally. What we hear
is the startup music once played. Only once, since upon finnishing Vec_Music_Flag
contains a zero, thus the Init_Music_chk knows the music is finnished and
nothing more is done. If we wanted to construct a program that played the
startup music continuesly, we would have need to check the above location,
and if we at some stage encounter a 0 we would have to fill it with another
initializing 1. That's all.
Now that we know how to play a piece of music let us go one step further,
and look what the piece of music is made of. Following text is simply copied
from the BIOS describtion done by Bruce Tomlin:
; Music data format: ;
; ;
; header word -> $C84F 32 nibble ADSR table ;
; header word -> $C851 8-byte "twang" table ;
; data bytes ;
; ;
; The ADSR table is simply 32 nibbles (16 bytes)
of amplitude values. ;
; ;
; The twang table is 8 signed bytes to modify
the base frequency of ;
; each note being played. Each channel has a
different limit to its ;
; twang table index (6-8) to keep them out of
phase to each other. ;
; ;
; Music data bytes: ;
; Bits 0-5 = frequency ;
; Bit 6 clear = tone ;
; Bit 6 set = noise ;
; Bit 7 set = next music data byte is for next
channel ;
; Bit 7 clear, play note with duration in next
music data byte: ;
; bits 0-5 = duration ;
; bit 6 = unused ;
; bit 7 set = end of music ;
It describes very well what a piece of music looks like. Usually you
will use a BIOS ADSR and TWANG table. But if you like experimenting you
can set up your own. There is no real magic about them.
The ADSR table sets up a 'fading' of the notes. If the fading is abrupt
it sounds very much like an old PONG game. If it last a bit longer you
can make it somewhat 'organ' like. If you are pretty clever with this you
can make it sound like different instruments.
The Twang table is for all pieces of music I know of for all bytes 0.
The Twang table is also called Vibe table, it sets up some sort of vibrato.
Actually I have not done much testing with that table but you sure can
come up with some weird sounds.
As you see, there is no magic about these values, and for most pieces
of music the BIOS provided once will be sufficient. Look at the ROM listing
and/or at Appendix A other ROM addresses, as
to where they are located, Minstorm including there are at least 6 different
to be found. The actual piece of music and how it is made up from the above
byte settings looks a bit confusing at first, but it really is pretty straight
forward. If you ever did some bit fiddling before you won't have any difficulties.
Let us give another small example, this time taken again from Vectrex Frogger:
sound2.asm
All that is changed from the program befor is the pointer of the music,
from music1 to yankee, and I added the yankee doodle music data.
The first two words of the data are BIOS ROM addresses of an ADSR and
a TWANG table. The TWANG table is as noted above, all zero, the ADSR table
looks like:
FEE8 FDB $EEFF,$FFEE,$EEDD,$CCBB,$AA99,$8888,$8888,$8888
As you can see there is not really all that much fading. It sounds a
bit organ like. Following are all notes. The first 26 notes are one voice
notes pretty low notes, actually they were supposed to sound a bit like
a drum, but using noise, sounded pretty bad, so I used 'tones' instead,
but took low notes. If you look at Appendix F you can easily translate
the values to notes, here a small extract:
G2 EQU $00 G = 1.5 8ves below middle C
GS2 EQU $01 G sharp (second 8ve) , etc.
A2 EQU $02
AS2 EQU $03
Thus the 2 means we are playing an A2 note, and the 0 means we are playing
a G2. The second byte in each line (when there are only two bytes) means
the length, for how long the note is played. The time is measured in milliseconds.
I wouldn't know how long a note must last, for it to be a quarter or
an eighth, but you probably would, I guess quarter about 16, eighth about
8 and so on. For the yankee doodle I took whatever came to my mind, and
I don't think it is very well done. Further down you will notice lines
that are somewhat more occupied. That's where I started using more than
one voice. Since we have only 64 notes, that means that the 7th (and 6)
bit of our note index is not used. Well it IS used afterall, if it is set
it means, that the following byte is not the time our note is supposed
to last, but a value which note the second (or third) voice should play.
There are a maximum of 3 voices. The missing sixth bit is used to indicate
whether the note should be played with a noise generator (bit 6 set) or
via a tone generator (bit 6 clear). The yankee doodle above does not make
use of the noise generator. The introduction music for armor attack (music3
($FD81)) is made up solely using the noise generator, it is supposed to
be snare drum pattern). After the data for the third voice a length (timing)
information must be given. The timing information also only has a length
of 6bit. The 6th bit is unsused. If the 7th bit is set, than the music
is over.
Next page Last
Page
Vectrex Programming TOC
|
|