|
Le code
Since I couldn't find any clear documentation about the contents of the ROMs (even in the patent) set apart for the cartridges "magic bytes" in a post of Lord Nightmare, I took the time to copy the assembler listing file in OO Calc (downloadable here). I commented most of the code for the main functions such as access to the ROMs, communication with the synthesizer, and the way "Spell mode" works. There's still the hangman, "Say it" and word scramble code left, which wasn't really interesting for what I wanted to know.
Note that the majority of the LDP instructions have been omitted in the Ti listing, ertainly to "mine" the code and prevent people from having a functional copy.
LDX, TCY: Load X, Y
CLA: Clear A
TAM TMA: Transfer A to RAM and vice versa
TMY: Transfer RAM in Y.
XMA: Swap A and RAM
TAMIYC: Transfer A to RAM and increment Y.
ACAAC: Add immediate to A
SBIT, RBIT: Set bit, Reset bit.
YNEC: Increment Y, and compare with value
SETR, RSTR: Set/reset line R #Y.
TKA: Read K lines.
TDO: Load the PLA.
...
Remember that the TMS1000 instruction set is available here.
By analyzing the code, I could understand how sentences were formed and what ROMs were accessed at what time.
There are different modes (games) available, but the best known is the one where a list of 10 words is randomly chosen internally, and each of these words is said before asking the user to write it correctly. Once these 10 words are done, the score is given then a new list is started.
When the S&S is turned on, this mode in level A (4 levels are available, A, B, C and D) and only the internal ROMs are used. The "Module select" button is used to read the words from the cartridge (That's for later...).
The number of words for the level is read from ROM at a fixed address, it's a 8-bit value so there can be a maximum of 255 words in each level.
A 12-bit internal counter which is normally used for the timeout for standby is used as a seed to generate a list of 10 words.
This seed is truncated to be less than the total number of words (DECLOOP routine).
The list is filled with 10 values beginning at this number. If the count exceeds the total number of words, it starts back at 0 (routine RPLOOP).
This list of "linear" values is then mixed up by inverting the values 2 by 2 (RSCRAM routine).
Once this list is made in RAM, it is expected that the player presses the "GO" button (or passes to another mode, the list remains in RAM anyways).
When the game is started, things get a bit complicated. It will seem confusing at first but bear with me.
The data for the first word in the RAM list needs to be read from the ROM.
To get this data, a 16-bit pointer corresponding to the chosen level is read at a fixed address.
This pointer leads to the start of a pointer table that match each word level. The word number multiplied by 2 is added to it (the pointers are 2 bytes), to fall on the right word data pointer. The new pointer is followed and finally gives the spelling data for the word.
The spelling is read byte by byte and stored in RAM. As the letters are coded on only 6 bits, bit #6 is used to indicate the last letter (letter code + 0x40). Remember that words can't be more than 8 characters, I'm not responsible for what may happen if you put more!
For example, the word "HOME" (see codes PLA), we find:
07 0E 0C 44
Immediately after the last spelling byte is a pointer to the audio data, data which won't be read by the microcontroller but by the synthesizer. This pointer is still used for the next step. More than one pointer can be provided to form sentences if necessary. The list of pointers is terminated with the value 0x0001.
Link list:
RAM |
Page 6 |
Page 7 |
0 |
Pointeur 1 |
1 |
2 |
Pointeur 2 |
3 |
4 |
Pointeur 3 |
5 |
6 |
Pointeur 4 |
7 |
8 |
Pointeur 5 |
9 |
10 |
Pointeur 6 |
11 |
12 |
Pointeur 7 |
13 |
14 |
Pointeur 8 |
15 |
A "link list" is made in RAM to form the phrase "Spell -word-". For this, the first entry is a fixed address in ROM of the word "Spell" and the second is the one of the last read pointer, so the selected word. The microcontroller then processes this link list by asking the synthesizer to say these words.
Let's get the spelling wrong, the microcontroller knows that this is the first try, it erases the link list and prepares a new to say "Wrong, try again". One might think that this sentence is in one block and a link list isn't necessary, but it turns out that the word "Wrong" is also used to tell the score. "Wrong" and "Try again" are two separate words in the ROM, to save space. So there is two addresses needed in the link list.
The link list is processed again, the try flag is set to 1 and the player is asked a second time to spell the word.
Let's suppose we're wrong again, the microcontroller knows that this is the second try and gives the correct spelling. A new list link is made to say "Wrong, the correct spelling of -word- is ...". There are 4 needed addresses in the link list: "Wrong", "The correct spelling of", the word, and "is". Once the list is processed, the correct spelling of the word is read letter by letter from RAM and each one is spoken. Then the next word is read...
Multiple pointers are used for hardly intelligible words such as "isle". For this word, the S&S says "Spell isle, as in island", there are 3 pointers in the word data: for "isle", "as in" and "island". "As in island" is not a whole block because "Island" is also used as a word in another level. Everything is done to save space. Note that in this case there are 4 pointers in the link list, with "Spell..." at the beginning. When the score is said, 5 pointers are found in the link list: "Here is your score", number, "Right", number, "Wrong."
The link list can store up to eight addresses. I am not responsible either for what may happen if this limit is exceeded ! (It should wrap to the first entry).
On cartridges (sometimes refered to as "external ROM"), the routine ADD8 adds or not an offset of 0x8000 to the address, thus pointing to the internal ROMs or the cartridge. Note that the cartridge is only used for the words, all the rest (phrases) remains in the internal ROM. This is why it is possible to have sentences such as "Spell maison" when a foreign cartridge is used. Pressing the "Module select" button switches this offset on/off and a new 10 words list is made each time.
With the code listing, I was also able to assemble a most of the RAM's memory map and the internal ROMs (see corresponding sheets in the OOffice file).
It can be seen, among other things, that the 8-bit values are not stored in the form of two consecutive words in the same page of RAM, but in two pages in parallel. For example, the VFD buffer is located in pages 0 (MSB) and 1 (LSB).
Pages 2 and 3 contain the buffer for the correct spelling of the word, and the counter for the standby and the generation of random numbers.
Pages 4 and 5 contain the list of words for the game (their numbers, not their addresses), and the total number of words in the selected level.
Pages 6 and 7 are used for the link list, and may contain a maximum of 8 16-bit addresses. These are the only 16-bit values stored in RAM.
For the ROM, it is possible to find interesting addresses around MEMADDR calls. For example, it is possible to find that the pointers to the LPC data for letters begin at 0x000C because in the NOSTRANS routine, 12 (0x0C) is added to the PLA code of the letter before passing the address to the synthesizer.
Memory map of the UK ROMs
Address |
Size (bytes) |
Description |
0 |
1 |
Word count of level A |
1 |
1 |
Word count of level B |
2 |
1 |
Word count of level C |
3 |
1 |
Word count of level D |
4 |
2 |
Pointer to the level A word list |
6 |
2 |
Pointer to the level B word list |
8 |
2 |
Pointer to the level C word list |
A |
2 |
Pointer to the level D word list |
C |
34 |
Pointer to the LPC of letters A~Z |
40 |
2 |
Pointer to the LPC of the apostrophe |
42 |
14 |
Pointer to the LPC of numbers 0~9 |
56 |
2 |
? |
58 |
2 |
Pointer to"That is correct" |
5A |
2 |
Pointer to"You are correct" |
5C |
2 |
Pointer to"That is right" |
5E |
2 |
Pointer to"You are right" |
60 |
2 |
Pointer to"(Now) spell" |
62 |
12 |
? |
6E |
2 |
Pointer to"Say it" |
70 |
2 |
Pointer to"I win" |
72 |
2 |
Pointer to"You win" |
74 |
2 |
Pointer to"Here is your score" |
76 |
2 |
? |
78 |
8 |
Pointers to groups of 4 tones |
80 |
128 |
Random letters table |
The rest contains tables of words, spellings and LPC data...
Memory map of the cartridges (universal)
Address |
Size (bytes) |
Description |
0 |
1 |
Word count of level A |
1 |
1 |
Word count of level B |
2 |
1 |
Word count of level C |
3 |
1 |
Word count of level D |
4 |
2 |
Pointer to the level A word list |
6 |
2 |
Pointer to the level B word list |
8 |
2 |
Pointer to the level C word list |
A |
2 |
Pointer to the level D word list |
C |
2 |
Magic bytes (0xAAAA) |
The rest is available for spellings and LPC data...
|