Mike,
I think we did it. The work you did debugging really helped a lot.
Here's what I learned:
The most important part of the code is what you labeled DoSpk.
Essentially it takes an address where the data begins, and the
address where the data ends, and one-by-one sends each bit to the
speaker port, 61h. If the bit is 1, it sends 32h. If the bit is 0
then it sends 30h. I traced it's progress as it spoke each
phoneme to learn their addresses.
Each phoneme is exactly 023Fh bytes long, and they are arranged
in sequence in the data table, in no particular order starting at
offset $012C. "I" is a special case which is always translated
into the pair "AH-EE". There is also a mystery "blank" phoneme.
So I wrote my own code for doing about the same thing as DoSpk.
This is in Talk.ASM. It requires TASM to assemble. It is passed
the address in memory where you want to start moving data to the
speaker, and the number of bytes you want processed. If you say
you want zero bytes, it processes 65536. It uses the value of a
global variable SpeedDelay to determine how much to slow down.
Altogether, it seems to be somewhat faster than the code used in
the original, so perhaps even a 4.77 MHz machine could use a
small delay. It is called ** FAR **.
Then I copied the data part of Speech.BIN to a file called
TalkData, and converted that to an object file with BINOBJ.
You'll have to run "BinObj TalkData.BIN TalkData.OBJ TalkDataLink".
I wrote routines in Pascal for parsing a string of phonemes, and
determining what values Talk needs.
TalkPhoneme takes just one phoneme and looks up it's address in
the table. The Turbo Pascal Seg and Ofs functions are used to
find the data table, and the constant data length, $023F, is hard
coded.
procedure Speech parses a string for phonemes. I'
|