diff options
Diffstat (limited to 'engines/queen/talk.cpp')
-rw-r--r-- | engines/queen/talk.cpp | 1812 |
1 files changed, 1812 insertions, 0 deletions
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp new file mode 100644 index 0000000000..27399ab0cf --- /dev/null +++ b/engines/queen/talk.cpp @@ -0,0 +1,1812 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2003-2006 The ScummVM project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/stdafx.h" +#include "queen/talk.h" + +#include "queen/bankman.h" +#include "queen/display.h" +#include "queen/graphics.h" +#include "queen/grid.h" +#include "queen/input.h" +#include "queen/logic.h" +#include "queen/queen.h" +#include "queen/resource.h" +#include "queen/sound.h" +#include "queen/state.h" +#include "queen/walk.h" + +#include "common/file.h" + +namespace Queen { + +#ifdef PALMOS_68K +static const Talk::SpeechParameters *_speechParameters; +#endif + +void Talk::talk( + const char *filename, + int personInRoom, + char *cutawayFilename, + QueenEngine *vm) { + Talk *talk = new Talk(vm); + talk->talk(filename, personInRoom, cutawayFilename); + delete talk; +} + +bool Talk::speak( + const char *sentence, + Person *person, + const char *voiceFilePrefix, + QueenEngine *vm) { + Talk *talk = new Talk(vm); + bool result; + if (sentence) + result = talk->speak(sentence, person, voiceFilePrefix); + else + result = false; + delete talk; + return result; +} + +Talk::Talk(QueenEngine *vm) + : _vm(vm), _fileData(NULL) { + _vm->input()->talkQuitReset(); +} + +Talk::~Talk() { + delete[] _fileData; +} + +void Talk::talk(const char *filename, int personInRoom, char *cutawayFilename) { + int i; + _oldSelectedSentenceIndex = 0; + _oldSelectedSentenceValue = 0; + + debug(6, "----- talk(\"%s\") -----", filename); + + cutawayFilename[0] = '\0'; + + load(filename); + + Person person; + memset(&person, 0, sizeof(Person)); + _vm->logic()->initPerson(personInRoom, "", false, &person); + + if (NULL == person.name) { + error("Invalid person object"); + } + + int16 oldLevel = 0; + bool personWalking = false; + + // Lines 828-846 in talk.c + for (i = 1; i <= 4; i++) { + if (selectedValue(i) > 0) { + // This option has been redefined so display new dialogue option + _dialogueTree[1][i].head = selectedValue(i); + } else if (selectedValue(i) == -1) { + // Already selected so don't redisplay + if (_dialogueTree[1][i].gameStateIndex >= 0) { + _dialogueTree[1][i].head = -1; + _dialogueTree[1][i].dialogueNodeValue1 = -1; + _dialogueTree[1][i].gameStateIndex = -1; + _dialogueTree[1][i].gameStateValue = -1; + } + } + } + + initialTalk(); + + // Lines 906-? in talk.c + _vm->display()->showMouseCursor(true); + + int16 level=1, retval=0; + int16 head = _dialogueTree[level][0].head; + + // TODO: split this loop in several functions + while (retval != -1) { + char otherVoiceFilePrefix[MAX_STRING_SIZE]; + + _talkString[0][0] = '\0'; + + if (hasTalkedTo() && head == 1) + strcpy(_talkString[0], _person2String); + else + findDialogueString(_person1PtrOff, head, _pMax, _talkString[0]); + + if (hasTalkedTo() && head == 1) + sprintf(otherVoiceFilePrefix, "%2dXXXXP", _talkKey); + else + sprintf(otherVoiceFilePrefix, "%2d%4xP", _talkKey, head); + + if (_talkString[0][0] == '\0' && retval > 1) { + findDialogueString(_person1PtrOff, retval, _pMax, _talkString[0]); + sprintf(otherVoiceFilePrefix,"%2d%4xP", _talkKey, retval); + } + + // Joe dialogue + + for (i = 1; i <= 4; i++) { + findDialogueString(_joePtrOff, _dialogueTree[level][i].head, _jMax, _talkString[i]); + + int16 index = _dialogueTree[level][i].gameStateIndex; + + if (index < 0 && _vm->logic()->gameState(ABS(index)) != _dialogueTree[level][i].gameStateValue) + _talkString[i][0] = '\0'; + + sprintf(_joeVoiceFilePrefix[i], "%2d%4xJ", _talkKey, _dialogueTree[level][i].head); + } + + // Check to see if (all the dialogue options have been selected. + // if this is the case, and the last one left is the exit option, + // then automatically set S to that and exit. + + int choicesLeft = 0; + int selectedSentence = 0; + + for (i = 1; i <= 4; i++) { + if (_talkString[i][0] != '\0') { + choicesLeft++; + selectedSentence = i; + } + } + + debug(6, "choicesLeft = %i", choicesLeft); + + if (1 == choicesLeft) { + // Automatically run the final dialogue option + if (speak(_talkString[0], &person, otherVoiceFilePrefix)) + personWalking = true; + + if (_vm->input()->talkQuit()) + break; + + speak(_talkString[selectedSentence], NULL, _joeVoiceFilePrefix[selectedSentence]); + } else { + if (person.actor->bobNum > 0) { + speak(_talkString[0], &person, otherVoiceFilePrefix); + selectedSentence = selectSentence(); + } else { + warning("bobBum is %i", person.actor->bobNum); + selectedSentence = 0; + } + } + + if (_vm->input()->talkQuit()) + break; + + retval = _dialogueTree[level][selectedSentence].dialogueNodeValue1; + head = _dialogueTree[level][selectedSentence].head; + oldLevel = level; + level = 0; + + // Set LEVEL to the selected child in dialogue tree + + for (i = 1; i <= _levelMax; i++) + if (_dialogueTree[i][0].head == head) + level = i; + + if (0 == level) { + // No new level has been selected, so lets set LEVEL to the + // tree path pointed to by the RETVAL + + for (i = 1; i <= _levelMax; i++) + for (int j = 0; j <= 5; j++) + if (_dialogueTree[i][j].head == retval) + level = i; + + disableSentence(oldLevel, selectedSentence); + } else { // 0 != level + // Check to see if Person Return value is positive, if it is, then + // change the selected dialogue option to the Return value + + if (_dialogueTree[level][0].dialogueNodeValue1 > 0) { + if (1 == oldLevel) { + _oldSelectedSentenceIndex = selectedSentence; + _oldSelectedSentenceValue = selectedValue(selectedSentence); + selectedValue(selectedSentence, _dialogueTree[level][0].dialogueNodeValue1); + } + + _dialogueTree[oldLevel][selectedSentence].head = _dialogueTree[level][0].dialogueNodeValue1; + _dialogueTree[level][0].dialogueNodeValue1 = -1; + } else { + disableSentence(oldLevel, selectedSentence); + } + } + + // Check selected person to see if any Gamestates need setting + + int16 index = _dialogueTree[level][0].gameStateIndex; + if (index > 0) + _vm->logic()->gameState(index, _dialogueTree[level][0].gameStateValue); + + // if the selected dialogue line has a POSITIVE game state value + // then set gamestate to Value = TALK(OLDLEVEL,S,3) + + index = _dialogueTree[oldLevel][selectedSentence].gameStateIndex; + if (index > 0) + _vm->logic()->gameState(index, _dialogueTree[oldLevel][selectedSentence].gameStateValue); + + // check to see if person has something final to say + if (-1 == retval) { + findDialogueString(_person1PtrOff, head, _pMax, _talkString[0]); + if (_talkString[0][0] != '\0') { + sprintf(otherVoiceFilePrefix, "%2d%4xP", _talkKey, head); + if (speak(_talkString[0], &person, otherVoiceFilePrefix)) + personWalking = true; + } + } + } + + cutawayFilename[0] = '\0'; + + for (i = 0; i < 2; i++) { + if (_gameState[i] > 0) { + if (_vm->logic()->gameState(_gameState[i]) == _testValue[i]) { + if (_itemNumber[i] > 0) + _vm->logic()->inventoryInsertItem(_itemNumber[i]); + else + _vm->logic()->inventoryDeleteItem(ABS(_itemNumber[i])); + } + } + } + + _vm->grid()->setupPanel(); + + uint16 offset = _cutawayPtrOff; + + int16 cutawayGameState = (int16)READ_BE_INT16(_fileData + offset); offset += 2; + int16 cutawayTestValue = (int16)READ_BE_INT16(_fileData + offset); offset += 2; + + if (_vm->logic()->gameState(cutawayGameState) == cutawayTestValue) { + getString(_fileData, offset, cutawayFilename, 20); + if (cutawayFilename[0]) { + //CR 2 - 7/3/95, If we're executing a cutaway scene, then make sure + // Joe can talk, so set TALKQUIT to 0 just in case we exit on the + // line that set's the cutaway game states. + _vm->input()->talkQuitReset(); + } + } + if (_vm->input()->talkQuit()) { + if (_oldSelectedSentenceIndex > 0) + selectedValue(_oldSelectedSentenceIndex, _oldSelectedSentenceValue); + _vm->input()->talkQuitReset(); + _vm->display()->clearTexts(0, 198); + _vm->logic()->makeJoeSpeak(15, false); + } else { + setHasTalkedTo(); + } + + _vm->logic()->joeFace(); + + if (cutawayFilename[0] == '\0') { + BobSlot *pbs = _vm->graphics()->bob(person.actor->bobNum); + + pbs->x = person.actor->x; + pbs->y = person.actor->y; + + // Better kick start the persons anim sequence + _vm->graphics()->resetPersonAnim(person.actor->bobNum); + } + + _vm->logic()->joeWalk(JWM_NORMAL); +} + +void Talk::disableSentence(int oldLevel, int selectedSentence) { + // Mark off selected option + + if (1 == oldLevel) { + if (_dialogueTree[oldLevel][selectedSentence].dialogueNodeValue1 != -1) { + // Make sure choice is not exit option + _oldSelectedSentenceIndex = selectedSentence; + _oldSelectedSentenceValue = selectedValue(selectedSentence); + selectedValue(selectedSentence, -1); + } + } + + // Cancel selected dialogue line, so that its no longer displayed + _dialogueTree[oldLevel][selectedSentence].head = -1; + _dialogueTree[oldLevel][selectedSentence].dialogueNodeValue1 = -1; +} + +void Talk::findDialogueString(uint16 offset, int16 id, int16 max, char *str) { + str[0] = '\0'; + for (int i = 1; i <= max; i++) { + offset += 2; + int16 currentId = (int16)READ_BE_INT16(_fileData + offset); + offset += 2; + if (id == currentId) { + getString(_fileData, offset, str, MAX_STRING_LENGTH, 4); + break; + } else { + getString(_fileData, offset, NULL, MAX_STRING_LENGTH, 4); + } + } +} + +byte *Talk::loadDialogFile(const char *filename) { + static const struct { + const char *filename; + Language lang; + } dogFiles[] = { + { "chief1.dog", FRENCH }, + { "chief2.dog", FRENCH }, + { "bud1.dog", ITALIAN } + }; + for (int i = 0; i < ARRAYSIZE(dogFiles); ++i) { + if (!scumm_stricmp(filename, dogFiles[i].filename) && + _vm->resource()->getLanguage() == dogFiles[i].lang) { + Common::File fdog; + fdog.open(filename); + if (fdog.isOpen()) { + debug(6, "Loading dog file '%s' from game data path", filename); + uint32 size = fdog.size() - DOG_HEADER_SIZE; + byte *buf = new byte[size]; + fdog.seek(DOG_HEADER_SIZE); + fdog.read(buf, size); + return buf; + } + } + } + return _vm->resource()->loadFile(filename, DOG_HEADER_SIZE); +} + +void Talk::load(const char *filename) { + int i; + byte *ptr = _fileData = loadDialogFile(filename); + bool canQuit; + + // Load talk header + + _levelMax = (int16)READ_BE_INT16(ptr); ptr += 2; + + if (_levelMax < 0) { + _levelMax = -_levelMax; + canQuit = false; + } else { + canQuit = true; + } + + _uniqueKey = (int16)READ_BE_INT16(ptr); ptr += 2; + _talkKey = (int16)READ_BE_INT16(ptr); ptr += 2; + _jMax = (int16)READ_BE_INT16(ptr); ptr += 2; + _pMax = (int16)READ_BE_INT16(ptr); ptr += 2; + + for (i = 0; i < 2; i++) { + _gameState [i] = (int16)READ_BE_INT16(ptr); ptr += 2; + _testValue [i] = (int16)READ_BE_INT16(ptr); ptr += 2; + _itemNumber[i] = (int16)READ_BE_INT16(ptr); ptr += 2; + } + + _person1PtrOff = READ_BE_UINT16(ptr); ptr += 2; + _cutawayPtrOff = READ_BE_UINT16(ptr); ptr += 2; + _person2PtrOff = READ_BE_UINT16(ptr); ptr += 2; + _joePtrOff = 32 + _levelMax * 96; + + // Load dialogue tree + ptr = _fileData + 32; + memset(&_dialogueTree[0], 0, sizeof(_dialogueTree[0])); + for (i = 1; i <= _levelMax; i++) + for (int j = 0; j <= 5; j++) { + ptr += 2; + _dialogueTree[i][j].head = (int16)READ_BE_INT16(ptr); ptr += 2; + ptr += 2; + _dialogueTree[i][j].dialogueNodeValue1 = (int16)READ_BE_INT16(ptr); ptr += 2; + ptr += 2; + _dialogueTree[i][j].gameStateIndex = (int16)READ_BE_INT16(ptr); ptr += 2; + ptr += 2; + _dialogueTree[i][j].gameStateValue = (int16)READ_BE_INT16(ptr); ptr += 2; + } +} + +void Talk::initialTalk() { + // Lines 848-903 in talk.c + + uint16 offset = _joePtrOff + 2; + uint16 hasNotString = READ_BE_UINT16(_fileData + offset); offset += 2; + + char joeString[MAX_STRING_SIZE]; + if (!hasNotString) { + getString(_fileData, offset, joeString, MAX_STRING_LENGTH); + } else { + joeString[0] = '\0'; + } + + offset = _person2PtrOff; + char joe2String[MAX_STRING_SIZE]; + getString(_fileData, offset, _person2String, MAX_STRING_LENGTH); + getString(_fileData, offset, joe2String, MAX_STRING_LENGTH); + + if (!hasTalkedTo()) { + // Not yet talked to this person + if (joeString[0] != '0') { + char voiceFilePrefix[MAX_STRING_SIZE]; + sprintf(voiceFilePrefix, "%2dSSSSJ", _talkKey); + speak(joeString, NULL, voiceFilePrefix); + } + } else { + // Already spoken to them, choose second response + if (joe2String[0] != '0') { + char voiceFilePrefix[MAX_STRING_SIZE]; + sprintf(voiceFilePrefix, "%2dXXXXJ", _talkKey); + speak(joe2String, NULL, voiceFilePrefix); + } + } +} + +int Talk::getSpeakCommand(const Person *person, const char *sentence, unsigned &index) { + // Lines 1299-1362 in talk.c + int commandCode = SPEAK_DEFAULT; + uint16 id = (sentence[index] << 8) | sentence[index + 1]; + switch (id) { + case 'AO': + commandCode = SPEAK_AMAL_ON; + break; + case 'FL': + commandCode = SPEAK_FACE_LEFT; + break; + case 'FF': + commandCode = SPEAK_FACE_FRONT; + break; + case 'FB': + commandCode = SPEAK_FACE_BACK; + break; + case 'FR': + commandCode = SPEAK_FACE_RIGHT; + break; + case 'GD': + _vm->logic()->joeGrab(STATE_GRAB_DOWN); + commandCode = SPEAK_NONE; + break; + case 'GM': + _vm->logic()->joeGrab(STATE_GRAB_MID); + commandCode = SPEAK_NONE; + break; + case 'WT': + commandCode = SPEAK_PAUSE; + break; + case 'XY': + // For example *XY00(237,112) + { + commandCode = atoi(sentence + index + 2); + int x = atoi(sentence + index + 5); + int y = atoi(sentence + index + 9); + if (0 == strcmp(person->name, "JOE")) + _vm->walk()->moveJoe(0, x, y, _vm->input()->cutawayRunning()); + else + _vm->walk()->movePerson(person, x, y, _vm->graphics()->numFrames(), 0); + index += 11; + // if (JOEWALK==3) CUTQUIT=0; + // XXX personWalking = true; + } + break; + default: + if (sentence[index + 0] >= '0' && sentence[index + 0] <= '9' && + sentence[index + 1] >= '0' && sentence[index + 1] <= '9') { + commandCode = (sentence[index] - '0') * 10 + (sentence[index + 1] - '0'); + } else + warning("Unknown command string: '%2s'", sentence + index); + } + + index += 2; + + return commandCode; +} + + +bool Talk::speak(const char *sentence, Person *person, const char *voiceFilePrefix) { + // Function SPEAK, lines 1266-1384 in talk.c + bool personWalking = false; + unsigned segmentIndex = 0; + unsigned segmentStart = 0; + unsigned i; + + Person joe_person; + ActorData joe_actor; + + _vm->logic()->joeWalk(JWM_SPEAK); + + if (!person) { + // Fill in values for use by speakSegment() etc. + memset(&joe_person, 0, sizeof(Person)); + memset(&joe_actor, 0, sizeof(ActorData)); + + joe_actor.bobNum = 0; + joe_actor.color = 14; + joe_actor.bankNum = 7; + + joe_person.actor = &joe_actor; + joe_person.name = "JOE"; + + person = &joe_person; + } + + debug(6, "Sentence '%s' is said by person '%s' and voice files with prefix '%s' played", + sentence, person->name, voiceFilePrefix); + + if (sentence[0] == '\0') { + return personWalking; + } + + if (0 == strcmp(person->name, "FAYE-H" ) || + 0 == strcmp(person->name, "FRANK-H") || + 0 == strcmp(person->name, "AZURA-H") || + 0 == strcmp(person->name, "X3_RITA") || + (0 == strcmp(person->name, "JOE") && _vm->logic()->currentRoom() == FAYE_HEAD ) || + (0 == strcmp(person->name, "JOE") && _vm->logic()->currentRoom() == AZURA_HEAD) || + (0 == strcmp(person->name, "JOE") && _vm->logic()->currentRoom() == FRANK_HEAD)) + _talkHead = true; + else + _talkHead = false; + + for (i = 0; i < strlen(sentence); ) { + if (sentence[i] == '*') { + int segmentLength = i - segmentStart; + + i++; + int command = getSpeakCommand(person, sentence, i); + + if (SPEAK_NONE != command) { + speakSegment( + sentence + segmentStart, + segmentLength, + person, + command, + voiceFilePrefix, + segmentIndex); + // XXX if (JOEWALK == 2) break + } + + segmentIndex++; + segmentStart = i; + } else + i++; + + if (_vm->input()->cutawayQuit() || _vm->input()->talkQuit()) + return personWalking; + } + + if (segmentStart != i) { + speakSegment( + sentence + segmentStart, + i - segmentStart, + person, + 0, + voiceFilePrefix, + segmentIndex); + } + + return personWalking; +} + +int Talk::countSpaces(const char *segment) { + int tmp = 0; + + while (*segment++) + tmp++; + + if (tmp < 10) + tmp = 10; + + return (tmp * 2) / (_vm->talkSpeed() / 3); +} + +void Talk::headStringAnimation(const SpeechParameters *parameters, int bobNum, int bankNum) { + // talk.c lines 1612-1635 + BobSlot *bob2 = _vm->graphics()->bob(2); + + if (parameters->animation[0] == 'E') { + int offset = 1; + + BobSlot *bob = _vm->graphics()->bob(bobNum); + int16 x = bob->x; + int16 y = bob->y; + + for (;;) { + uint16 frame; + + frame = atoi(parameters->animation + offset); + if (!frame) + break; + + offset += 4; + + _vm->bankMan()->unpack(frame, _vm->graphics()->numFrames(), bankNum); + + bob2->frameNum = _vm->graphics()->numFrames(); + bob2->scale = 100; + bob2->active = true; + bob2->x = x; + bob2->y = y; + + _vm->update(); + } + } else + bob2->active = false; +} + +void Talk::stringAnimation(const SpeechParameters *parameters, int startFrame, int bankNum) { + // lines 1639-1690 in talk.c + + int offset = 0; + bool torso; + + if (parameters->animation[0] == 'T') { + // Torso animation + torso = true; + _vm->bankMan()->overpack(parameters->body, startFrame, bankNum); + offset++; + } else if (parameters->animation[0] == 'E') { + // Talking head animation + return; + } else if (!isdigit(parameters->animation[0])) { + debug(6, "Error in speak string animation: '%s'", parameters->animation); + return; + } else + torso = false; + + for (;;) { + uint16 frame; + + frame = atoi(parameters->animation + offset); + if (!frame) + break; + + offset += 4; + + if (frame > 500) { + frame -= 500; + _vm->sound()->playSfx(_vm->logic()->currentRoomSfx(), false); + } + + if (torso) { + _vm->bankMan()->overpack(frame, startFrame, bankNum); + } else { + _vm->bankMan()->unpack(frame, startFrame, bankNum); + // XXX bobs[BNUM].scale=SF; + } + + _vm->update(); + } +} + +void Talk::defaultAnimation( + const char *segment, + bool isJoe, + const SpeechParameters *parameters, + int startFrame, + int bankNum) { + // lines 1730-1823 in talk.c + + if (segment[0] != 0) { + + // Why on earth would someone name a variable qzx? + short qzx = 0; + + int len = countSpaces(segment); + while (1) { + if (parameters != NULL) { + + int bf; + if (segment[0] == ' ') + bf = 0; + else + bf = parameters->bf; + + int head; + if (parameters->rf > 0) + head = bf + _vm->randomizer.getRandomNumber(parameters->rf); + else + head = bf; + + if (bf > 0) { + // Make the head move + qzx ^= 1; + if (parameters->af && qzx) + _vm->bankMan()->overpack(parameters->af + head, startFrame, bankNum); + else { + _vm->bankMan()->overpack(head, startFrame, bankNum); + } + } else { + debug(6, "[Talk::defaultAnimation] Body action!"); + // Just do a body action + _vm->bankMan()->overpack(parameters->body, startFrame, bankNum); + } + + if (!_talkHead) + _vm->update(); + } else { // (_talkHead && isJoe) + _vm->update(); + } + + if (_vm->input()->talkQuit()) + break; + + if (_vm->logic()->joeWalk() == JWM_SPEAK) { + _vm->update(); + } else { + _vm->update(true); + if (_vm->logic()->joeWalk() == JWM_EXECUTE) + // Selected a command, so exit + break; + } + + // Skip through text more quickly + if (_vm->input()->keyVerb() == VERB_SKIP_TEXT) { + _vm->input()->clearKeyVerb(); + _vm->sound()->stopSpeech(); + break; + } + + if (_vm->sound()->speechOn() && _vm->sound()->speechSfxExists()) { + // sfx is finished, stop the speak animation + if (!_vm->sound()->isSpeechActive()) { + break; + } + } else { + // no sfx, stop the animation when speak segment 'length' is 0 + --len; + if (len <= 0) { + break; + } + } + } + } + + // Make sure that Person closes their mouth + if (!isJoe && parameters->ff > 0) + _vm->bankMan()->overpack(parameters->ff, startFrame, bankNum); +} + + +void Talk::speakSegment( + const char *segmentStart, + int length, + Person *person, + int command, + const char *voiceFilePrefix, + int index) +{ + int i; + char segment[MAX_STRING_SIZE]; + memcpy(segment, segmentStart, length); + segment[length] = '\0'; + + char voiceFileName[MAX_STRING_SIZE]; + sprintf(voiceFileName, "%s%1x", voiceFilePrefix, index + 1); + + // FIXME - it seems the french talkie version has a useless voice file ; + // the c30e_102 file is very similar to c30e_101, so there is no need to + // play it. This voice was used in room 30 (N8) when talking to Klunk. + if (!(_vm->resource()->getLanguage() == FRENCH && !strcmp(voiceFileName, "c30e_102")) + && _vm->sound()->speechOn()) + _vm->sound()->playSfx(voiceFileName, true); + + int faceDirectionCommand = 0; + + switch (command) { + case SPEAK_PAUSE: + for (i = 0; i < 10 && !_vm->input()->talkQuit(); i++) { + _vm->update(); + } + return; + + case SPEAK_FACE_LEFT: + case SPEAK_FACE_RIGHT: + case SPEAK_FACE_FRONT: + case SPEAK_FACE_BACK: + faceDirectionCommand = command; + command = 0; + break; + } + + bool isJoe = (0 == person->actor->bobNum); + + int16 bobNum = person->actor->bobNum; + uint16 color = person->actor->color; + uint16 bankNum = person->actor->bankNum; + + BobSlot *bob = _vm->graphics()->bob(bobNum); + + bool oracle = false; + int textX = 0; + int textY = 0; + + if (!isJoe) { + if (SPEAK_AMAL_ON == command) { + // It's the oracle! + // Don't turn AMAL animation off, and don't manually anim person + command = SPEAK_ORACLE; + oracle = true; + uint16 frameNum = _vm->graphics()->personFrames(bobNum); + for (i = 5; i <= 8; ++i) { + _vm->bankMan()->unpack(i, frameNum, bankNum); + ++frameNum; + } + } else { + bob->animating = false; + bob->frameNum = 31 + bobNum; + } + } + + if (_talkHead) { + // talk.c lines 1491-1533 + switch (_vm->logic()->currentRoom()) { + case FAYE_HEAD: + case AZURA_HEAD: + textX = 15; + break; + default: // FRANK_HEAD + textX = 150; + break; + } + textY = isJoe ? 30 : 60; + } else { + textX = bob->x; + textY = bob->y; + } + + //int SF = _vm->grid()->findScale(textX, textY); + + const SpeechParameters *parameters = NULL; + int startFrame = 0; + + if (_talkHead && isJoe) { + if (_vm->subtitles()) + _vm->graphics()->setBobText(bob, segment, textX, textY, color, true); + defaultAnimation(segment, isJoe, parameters, startFrame, bankNum); + } else { + if (SPEAK_UNKNOWN_6 == command) + return; + + if (isJoe) { + if (_vm->logic()->currentRoom() == 108) + parameters = findSpeechParameters("JOE-E", command, 0); + else + parameters = findSpeechParameters("JOE", command, _vm->logic()->joeFacing()); + } + else + parameters = findSpeechParameters(person->name, command, 0); + + startFrame = 31 + bobNum; + int faceDirection = 0; + + if (isJoe && _vm->logic()->joeFacing() == DIR_LEFT) + faceDirection = DIR_LEFT; + else if (!isJoe) { + ObjectData *data = _vm->logic()->objectData(_vm->logic()->objectForPerson(bobNum)); + + if (data->image == -3) + faceDirection = DIR_LEFT; + + if (faceDirectionCommand == SPEAK_FACE_LEFT) + data->image = -3; + else if (faceDirectionCommand == SPEAK_FACE_RIGHT) + data->image = -4; + } + + if (faceDirectionCommand) { + switch (faceDirectionCommand) { + case SPEAK_FACE_LEFT: + faceDirection = DIR_LEFT; + break; + case SPEAK_FACE_RIGHT: + faceDirection = DIR_RIGHT; + break; + case SPEAK_FACE_FRONT: + faceDirection = DIR_FRONT; + break; + case SPEAK_FACE_BACK: + faceDirection = DIR_BACK; + break; + } + if (isJoe) + _vm->logic()->joeFacing(faceDirection); + } + + if (!isJoe) { + bob->xflip = (faceDirection == DIR_LEFT); + } + + // Run animated sequence if SANIMstr is primed + + if (_talkHead) { + // talk.c lines 1612-1635 + headStringAnimation(parameters, bobNum, bankNum); + } + + if (_vm->subtitles()) + _vm->graphics()->setBobText(bob, segment, textX, textY, color, _talkHead); + + if (parameters->animation[0] != '\0' && parameters->animation[0] != 'E') { + stringAnimation(parameters, startFrame, bankNum); + } else { + _vm->bankMan()->unpack(parameters->body, startFrame, bankNum); + + if (length == 0 && !isJoe && parameters->bf > 0) { + _vm->bankMan()->overpack(parameters->bf, startFrame, bankNum); + _vm->update(); + } + + if (-1 == parameters->rf) { + // Setup the Torso frames + _vm->bankMan()->overpack(parameters->bf, startFrame, bankNum); + if (isJoe) + parameters = findSpeechParameters(person->name, 0, _vm->logic()->joeFacing()); + else + parameters = findSpeechParameters(person->name, 0, 0); + } + + if (-2 == parameters->rf) { + // Setup the Torso frames + _vm->bankMan()->overpack(parameters->bf, startFrame, bankNum); + if (isJoe) + parameters = findSpeechParameters(person->name, 14, _vm->logic()->joeFacing()); + else + parameters = findSpeechParameters(person->name, 14, 0); + } + + defaultAnimation(segment, isJoe, parameters, startFrame, bankNum); + } + } + + // Moved here so that Text is cleared when a Torso command done! + _vm->display()->clearTexts(0,198); + + if (oracle) { + uint16 frameNum = _vm->graphics()->personFrames(bobNum); + for (i = 1; i <= 4; ++i) { + _vm->bankMan()->unpack(i, frameNum, bankNum); + ++frameNum; + } + } + + // Ensure that the correct buffer frame is selected + + if (isJoe && !_talkHead) { + if (_vm->logic()->joeFacing() == DIR_FRONT || + _vm->logic()->joeFacing() == DIR_BACK) { + // Joe is facing either Front or Back! + // - Don't FACE_JOE in room 69, because Joe is probably + // holding the Dino Ray gun. + if (_vm->logic()->currentRoom() != 69) + _vm->logic()->joeFace(); + } else { + if (command == SPEAK_DEFAULT || + command == 6 || + command == 7) { + _vm->logic()->joeFace(); + } else if (command != 5) { + // 7/11/94, Ensure that correct mouth closed frame is used! + if (parameters->rf != -1) + // XXX should really be just "bf", but it is not always calculated... :-( + _vm->bankMan()->overpack(parameters->bf, startFrame, bankNum); + + if (parameters->ff == 0) + _vm->bankMan()->overpack(10, startFrame, bankNum); + else + _vm->bankMan()->overpack(parameters->ff, startFrame, bankNum); + } + } + } + + _vm->update(); +} + +const Talk::SpeechParameters *Talk::findSpeechParameters( + const char *name, + int state, + int faceDirection) { + const SpeechParameters *iterator = _speechParameters; + if (faceDirection == DIR_RIGHT) + faceDirection = DIR_LEFT; + + while (iterator->name[0] != '*') { + if (0 == scumm_stricmp(iterator->name, name) && + iterator->state == state && + iterator->faceDirection == faceDirection) + break; + iterator++; + } + + return iterator; +} + +void Talk::getString(const byte *ptr, uint16 &offset, char *str, int maxLength, int align) { + assert((align & 1) == 0); + int length = *(ptr + offset); + ++offset; + + if (length > maxLength) { + error("String too long. Length = %i, maxLength = %i", length, maxLength); + } else if (length) { + if (str) { + memcpy(str, ptr + offset, length); + str[length] = '\0'; + } + offset = (offset + length + (align - 1)) & ~(align - 1); + } else { + if (str) { + str[0] = '\0'; + } + } +} + +TalkSelected *Talk::talkSelected() { + return _vm->logic()->talkSelected(_uniqueKey); +} + +int Talk::splitOption(const char *str, char optionText[5][MAX_STRING_SIZE]) { + char option[MAX_STRING_SIZE]; + strcpy(option, str); + // option text ends at '*' char + char *p = strchr(option, '*'); + if (p) { + *p = '\0'; + } + int lines; + memset(optionText, 0, 5 * MAX_STRING_SIZE); + if (_vm->resource()->getLanguage() == ENGLISH || _vm->display()->textWidth(option) <= MAX_TEXT_WIDTH) { + strcpy(optionText[0], option); + lines = 1; + } else if (_vm->resource()->getLanguage() == HEBREW) { + lines = splitOptionHebrew(option, optionText); + } else { + lines = splitOptionDefault(option, optionText); + } + return lines; +} + +int Talk::splitOptionHebrew(const char *str, char optionText[5][MAX_STRING_SIZE]) { + char tmpString[MAX_STRING_SIZE] = ""; + uint16 len = 0; + uint16 spaceCharWidth = _vm->display()->textWidth(" "); + uint16 width = 0; + uint16 optionLines = 0; + uint16 maxTextLen = MAX_TEXT_WIDTH; + const char *p = strchr(str, '\0'); + while (p != str - 1) { + while (*p != ' ' && p != str - 1) { + --p; + ++len; + } + if (p != str - 1) { + uint16 wordWidth = _vm->display()->textWidth(p, len); + width += wordWidth; + if (width > maxTextLen) { + ++optionLines; + strncpy(optionText[optionLines], p, len); + optionText[optionLines][len] = '\0'; + width = wordWidth; + maxTextLen = MAX_TEXT_WIDTH - OPTION_TEXT_MARGIN; + } else { + strcpy(tmpString, optionText[optionLines]); + strncpy(optionText[optionLines], p, len); + optionText[optionLines][len] = '\0'; + strcat(optionText[optionLines], tmpString); + } + --p; + len = 1; + width += spaceCharWidth; + } else { + if (len > 1) { + if (width + _vm->display()->textWidth(p + 1, len) > maxTextLen) { + ++optionLines; + } + strcpy(tmpString, optionText[optionLines]); + strncpy(optionText[optionLines], p + 1, len); + optionText[optionLines][len] = '\0'; + strcat(optionText[optionLines], tmpString); + } + ++optionLines; + } + } + return optionLines; +} + +int Talk::splitOptionDefault(const char *str, char optionText[5][MAX_STRING_SIZE]) { + // Split up multiple line option at closest space character + uint16 spaceCharWidth = _vm->display()->textWidth(" "); + uint16 width = 0; + uint16 optionLines = 0; + uint16 maxTextLen = MAX_TEXT_WIDTH; + const char *p = str; + while (p) { + p = strchr(str, ' '); + if (p) { + uint16 len = p - str; + uint16 wordWidth = _vm->display()->textWidth(str, len); + width += wordWidth; + if (width > maxTextLen) { + ++optionLines; + strncpy(optionText[optionLines], str, len + 1); + width = wordWidth; + maxTextLen = MAX_TEXT_WIDTH - OPTION_TEXT_MARGIN; + } else { + strncat(optionText[optionLines], str, len + 1); + } + width += spaceCharWidth; + str = p + 1; + } else { + if (str[0]) { + if (width + _vm->display()->textWidth(str) > maxTextLen) { + ++optionLines; + } + strcat(optionText[optionLines], str); + } + ++optionLines; + } + } + return optionLines; +} + +int16 Talk::selectSentence() { + int selectedSentence = 0; + + int startOption = 1; + int optionLines = 0; + char optionText[5][MAX_STRING_SIZE]; + int talkZone[5]; + int i; + + _vm->display()->textCurrentColor(INK_TALK_NORMAL); + + _vm->graphics()->setupArrows(); + BobSlot *arrowBobUp = _vm->graphics()->bob(Graphics::ARROW_BOB_UP); + arrowBobUp->active = false; + BobSlot *arrowBobDown = _vm->graphics()->bob(Graphics::ARROW_BOB_DOWN); + arrowBobDown->active = false; + + bool rezone = true; + + while (rezone) { + rezone = false; + + // Set zones for UP/DOWN text arrows when not English version + + _vm->grid()->clear(GS_PANEL); + + if (_vm->resource()->getLanguage() != ENGLISH) { + _vm->grid()->setZone(GS_PANEL, ARROW_ZONE_UP, MAX_TEXT_WIDTH + 1, 0, 319, 24); + _vm->grid()->setZone(GS_PANEL, ARROW_ZONE_DOWN, MAX_TEXT_WIDTH + 1, 25, 319, 49); + } + + _vm->display()->clearTexts(151, 199); + + int sentenceCount = 0; + int yOffset = 1; + + for (i = startOption; i <= 4; i++) { + talkZone[i] = 0; + + if (_talkString[i][0] != '\0') { + sentenceCount++; + optionLines = splitOption(_talkString[i], optionText); + + if (yOffset < 5) { + _vm->grid()->setZone( + GS_PANEL, + i, + 0, + yOffset * LINE_HEIGHT - PUSHUP, + (_vm->resource()->getLanguage() == ENGLISH) ? 319 : MAX_TEXT_WIDTH, + (yOffset + optionLines) * LINE_HEIGHT - PUSHUP); + } + + int j; + for (j = 0; j < optionLines; j++) { + if (yOffset < 5) { + _vm->display()->setText( + (j == 0) ? 0 : OPTION_TEXT_MARGIN, + 150 - PUSHUP + yOffset * LINE_HEIGHT, + optionText[j]); + } + yOffset++; + } + + talkZone[i] = sentenceCount; + } + } + + yOffset--; + + // Up and down dialogue arrows + + if (_vm->resource()->getLanguage() != ENGLISH) { + arrowBobUp->active = (startOption > 1); + arrowBobDown->active = (yOffset > 4); + } + + _vm->input()->clearKeyVerb(); + + if (sentenceCount > 0) { + int zone = 0; + int oldZone = 0; + + while (0 == selectedSentence) { + + if (_vm->input()->talkQuit()) + break; + + _vm->update(); + + zone = _vm->grid()->findZoneForPos(GS_PANEL, _vm->input()->mousePosX(), _vm->input()->mousePosY()); + + int mouseButton = _vm->input()->mouseButton(); + _vm->input()->clearMouseButton(); + + if (ARROW_ZONE_UP == zone || ARROW_ZONE_DOWN == zone) { + if (oldZone > 0) { + int16 y; + const Box *b = _vm->grid()->zone(GS_PANEL, oldZone); + for (y = b->y1; y < b->y2; y += 10) + _vm->display()->textColor(150 + y, INK_TALK_NORMAL); + oldZone = 0; + } + if (mouseButton != 0) { + if (zone == ARROW_ZONE_UP && arrowBobUp->active) { + startOption--; + } else if (zone == ARROW_ZONE_DOWN && arrowBobDown->active) { + startOption++; + } + } + rezone = true; + break; + } else { + if (oldZone != zone) { + // Changed zone, change text colors + int y; + + debug(6, "Changed zone. oldZone = %i, zone = %i", + oldZone, zone); + + if (zone > 0) { + const Box *b = _vm->grid()->zone(GS_PANEL, zone); + for (y = b->y1; y < b->y2; y += 10) + _vm->display()->textColor(150 + y, INK_JOE); + } + + if (oldZone > 0) { + const Box *b = _vm->grid()->zone(GS_PANEL, oldZone); + for (y = b->y1; y < b->y2; y += 10) + _vm->display()->textColor(150 + y, INK_TALK_NORMAL); + } + + oldZone = zone; + } + + } + + Verb v = _vm->input()->keyVerb(); + if (v >= VERB_DIGIT_FIRST && v <= VERB_DIGIT_LAST) { + int n = v - VERB_DIGIT_FIRST + 1; + for (i = 1; i <= 4; i++) { + if (talkZone[i] == n) { + selectedSentence = i; + break; + } + } + + _vm->input()->clearKeyVerb(); + } + else if (mouseButton) { + selectedSentence = zone; + } + + } // while () + } + } + + debug(6, "Selected sentence %i", selectedSentence); + + arrowBobUp->active = false; + arrowBobDown->active = false; + + if (selectedSentence > 0) { + _vm->display()->clearTexts(0, 198); + + speak(_talkString[selectedSentence], NULL, _joeVoiceFilePrefix[selectedSentence]); + } + + _vm->display()->clearTexts(151, 151); + + return selectedSentence; +} + +#ifndef PALMOS_68K +const Talk::SpeechParameters Talk::_speechParameters[] = { + { "JOE", 0, 1, 1, 10, 2, 3, "", 0 }, + { "JOE", 0, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 0, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 1, 1, 1, 45, -1, 0, "", 0 }, + { "JOE", 1, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 1, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 2, 1, 1, 46, -1, 0, "", 0 }, + { "JOE", 2, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 2, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 3, 1, 1, 47, -1, 0, "", 0 }, + { "JOE", 3, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 3, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 4, 1, 1, 50, -1, 0, "", 0 }, + { "JOE", 4, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 4, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 5, 1, 2, 0, 0, 0, "", 0 }, + { "JOE", 5, 3, 4, 0, 0, 0, "", 0 }, + { "JOE", 5, 4, 6, 0, 0, 0, "", 0 }, + + { "JOE", 6, 1, 1, 48, 0, 1, "", 0 }, + { "JOE", 6, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 6, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 7, 1, 1, 51, 0, 1, "", 0 }, + { "JOE", 7, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 7, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 8, 1, 1, 26, 0, 0, "", 0 }, + { "JOE", 8, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 8, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 9, 1, 1, 29, 0, 0, "", 0 }, + { "JOE", 9, 3, 3, 28, 0, 0, "", 0 }, + { "JOE", 9, 4, 5, 38, 0, 0, "", 0 }, + + { "JOE", 10, 1, 1, 12, 0, 0, "T046,010,010,010,012,012,012,012,012,012,012,012,012,012,012,012,012,012,010,000", 0 }, + { "JOE", 10, 3, 3, 18, 0, 0, "", 0 }, + { "JOE", 10, 4, 5, 44, 0, 0, "", 0 }, + + { "JOE", 11, 1, 1, 53, -1, 0, "", 0 }, + { "JOE", 11, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 11, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 12, 1, 1, 10, 2, 3, "", 0 }, + { "JOE", 12, 3, 3, 28, 2, 0, "", 0 }, + { "JOE", 12, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 13, 1, 1, 10, 2, 3, "T012,013,019,019,019,019,019,019,019,019,019,019,013,010,000", 0 }, + { "JOE", 13, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 13, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 14, 1, 1, 16, 2, 3, "", 16 }, + { "JOE", 14, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 14, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 15, 1, 1, 58, -1, 0, "", 0 }, + { "JOE", 15, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 15, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 16, 1, 1, 59, -1, 0, "", 0 }, + { "JOE", 16, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 16, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 17, 1, 1, 56, -1, 0, "", 0 }, + { "JOE", 17, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 17, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 18, 1, 56, 16, 2, 3, "T056,057,057,057,056,056,000", 0 }, + { "JOE", 18, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 18, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 19, 1, 54, 16, 2, 3, "T054,055,057,056,000", 0 }, + { "JOE", 19, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 19, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 20, 1, 56, 16, 2, 3, "T056,057,055,054,001,000", 0 }, + { "JOE", 20, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 20, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 21, 1, 1, 60, -1, 0, "", 0 }, + { "JOE", 21, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 21, 4, 61, 38, 1, 0, "", 0 }, + + { "JOE", 22, 1, 1, 16, 2, 3, "T063,060,000", 0 }, + { "JOE", 22, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 22, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 23, 1, 1, 16, 2, 3, "T060,063,001,000", 0 }, + { "JOE", 23, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 23, 4, 5, 38, 1, 0, "", 0 }, + + { "JOE", 24, 1, 1, 47, -2, 0, "", 0 }, + { "JOE", 24, 3, 3, 28, 2, 3, "", 0 }, + { "JOE", 24, 4, 5, 38, 1, 0, "", 0 }, + + { "RICO", 0, 0, 1, 7, 1, 3, "", 7 }, + { "RICO", 1, 0, 1, 5, -1, 0, "", 7 }, + { "RICO", 2, 0, 1, 9, 0, 3, "", 7 }, + { "RICO", 3, 0, 1, 4, -1, 0, "", 7 }, + + { "EDDY", 0, 0, 14, 18, 1, 3, "", 18 }, + { "EDDY", 1, 0, 14, 0, 0, 0, "T016,017,017,016,016,017,017,016,016,017,017,000", 18 }, + + { "MIKE", 0, 0, 1, 2, 2, 3, "", 2 }, + + { "LOLA", 0, 0, 30, 33, 2, 3, "", 33 }, + { "LOLA", 1, 0, 9, 10, 2, 3, "", 33 }, + { "LOLA", 2, 0, 30, 33, 2, 3, "", 33 }, + { "LOLA", 3, 0, 32, 33, 2, 3, "", 33 }, + { "LOLA", 4, 0, 8, 0, 0, 0, "", 33 }, + { "LOLA", 5, 0, 31, 0, 0, 0, "", 0 }, + { "LOLA", 6, 0, 31, 0, 0, 0, "047,048,049,050,000", 33 }, + + { "LOLA_SHOWER", 0, 0, 7, 10, 2, 3, "", 10 }, + { "LOLA_SHOWER", 1, 0, 9, 10, 2, 3, "", 10 }, + { "LOLA_SHOWER", 2, 0, 30, 33, 2, 3, "", 10 }, + { "LOLA_SHOWER", 3, 0, 32, 33, 2, 3, "", 10 }, + { "LOLA_SHOWER", 4, 0, 8, 0, 0, 0, "", 0 }, + { "LOLA_SHOWER", 5, 0, 61, 0, 0, 0, "", 0 }, + { "LOLA_SHOWER", 6, 0, 64, 10, 2, 3, "", 0 }, + { "LOLA_SHOWER", 7, 0, 31, 0, 0, 0, "062,063,064,000", 0 }, + + { "SECRETARY", 0, 0, 1, 12, 2, 3, "", 12 }, + { "SECRETARY", 1, 0, 1, 12, 2, 0, "", 12 }, + { "SECRETARY", 2, 0, 1, 12, 2, 0, "", 12 }, + + { "SPARKY", 0, 0, 21, 23, 2, 3, "", 23 }, + { "SPARKY", 1, 0, 21, 22, 0, 0, "", 0 }, + { "SPARKY", 2, 0, 21, 22, 0, 0, "021,042,043,000", 0 }, + { "SPARKY", 3, 0, 21, 22, 0, 0, "043,042,021,000", 0 }, + { "SPARKY", 4, 0, 43, 43, 1, 0, "", 0 }, + { "SPARKY", 14, 0, 21, 29, 5, 0, "", 29 }, + + { "SPARKY-F", 0, 0, 45, 23, 5, 0, "", 23 }, + { "SPARKY-F", 1, 0, 45, 47, 0, 0, "", 0 }, + { "SPARKY-F", 2, 0, 45, 23, 5, 0, "045,046,046,045,000", 23 }, + { "SPARKY-F", 14, 0, 45, 29, 5, 0, "", 29 }, + + { "FAYE", 0, 0, 19, 35, 2, 3, "", 35 }, + { "FAYE", 1, 0, 19, 41, 2, 3, "", 35 }, + { "FAYE", 2, 0, 19, 28, -1, 0, "", 35 }, + { "FAYE", 3, 0, 19, 20, 0, 0, "", 0 }, + { "FAYE", 4, 0, 19, 27, -1, 0, "", 35 }, + { "FAYE", 5, 0, 19, 29, -1, 0, "", 35 }, + { "FAYE", 6, 0, 59, 35, 2, 3, "", 35 }, + { "FAYE", 7, 0, 19, 30, -1, 0, "", 35 }, + { "FAYE", 8, 0, 19, 31, -1, 0, "", 35 }, + + { "BOB", 0, 0, 27, 34, 2, 3, "", 34 }, + { "BOB", 1, 0, 27, 28, -1, 0, "", 34 }, + { "BOB", 2, 0, 30, 0, 0, 0, "", 0 }, + { "BOB", 3, 0, 31, 0, 0, 0, "", 0 }, + { "BOB", 4, 0, 27, 61, -1, 0, "", 34 }, + { "BOB", 5, 0, 27, 42, 1, 0, "", 42 }, + + { "PYGMY", 0, 0, 20, 21, 2, 6, "", 0 }, + { "PYGMY", 1, 0, 20, 21, 2, 6, "020,068,068,068,068,068,068,068,068,020,000", 0 }, + { "PYGMY", 2, 0, 20, 21, 2, 6, "T028,029,030,031,031,031,031,030,029,028,035,000", 0 }, + { "PYGMY", 3, 0, 20, 21, 2, 6, "T035,036,037,038,037,038,037,038,036,035,000", 0 }, + { "PYGMY", 4, 0, 20, 21, 2, 6, "T032,033,032,033,032,033,035,000", 0 }, + { "PYGMY", 5, 0, 20, 21, 2, 6, "T023,022,021,022,023,024,025,026,027,026,025,024,023,000", 0 }, + { "PYGMY", 6, 0, 20, 21, 2, 6, "T034,034,034,035,000", 0 }, + + { "WITCH", 0, 0, 39, 40, 2, 6, "", 40 }, + { "WITCH", 1, 0, 39, 40, 2, 6, "073,074,000", 40 }, + { "WITCH", 2, 0, 39, 40, 2, 6, "074,073,000", 40 }, + { "WITCH", 3, 0, 39, 40, 2, 6, "T047,048,049,050,051,000", 40 }, + { "WITCH", 4, 0, 39, 40, 2, 6, "T052,053,054,055,056,057,058,057,056,056,056,055,054,053,052,000", 40 }, + { "WITCH", 5, 0, 39, 40, 2, 6, "069,070,071,072,073,074,000", 40 }, + { "WITCH", 6, 0, 39, 40, 2, 6, "074,073,072,071,070,069,070,000", 40 }, + { "WITCH", 7, 0, 39, 51, -1, 0, "", 40 }, + { "WITCH", 8, 0, 39, 40, 2, 6, "T051,050,049,048,047,000", 40 }, + + { "CHIEF", 0, 0, 1, 7, 1, 7, "", 3 }, + { "CHIEF", 1, 0, 1, 2, 2, 6, "062,063,064,065,066,000", 0 }, + { "CHIEF", 2, 0, 1, 2, 2, 6, "066,065,064,063,062,000", 0 }, + { "CHIEF", 3, 0, 1, 17, -1, 0, "", 3 }, + { "CHIEF", 4, 0, 1, 18, -1, 0, "", 3 }, + { "CHIEF", 5, 0, 1, 19, -1, 0, "", 3 }, + + { "NAOMI", 0, 0, 1, 2, 2, 3, "", 2 }, + { "NAOMI", 1, 0, 1, 2, 2, 6, "048,049,050,051,052,053,054,055,000", 0 }, + { "NAOMI", 2, 0, 1, 2, 2, 6, "055,054,053,052,051,050,049,048,000", 0 }, + { "NAOMI", 3, 0, 1, 13, -1, 0, "", 2 }, + { "NAOMI", 4, 0, 1, 14, -1, 0, "", 2 }, + { "NAOMI", 5, 0, 1, 10, -1, 0, "", 2 }, + { "NAOMI", 6, 0, 1, 12, -1, 0, "", 2 }, + { "NAOMI", 7, 0, 1, 12, -1, 0, "T008,008,008,002,000", 2 }, + + { "WEDGEWOOD", 0, 0, 8, 1, 2, 0, "", 8 }, + { "WEDGEWOOD", 1, 0, 1, 1, 3, 0, "", 1 }, + + { "BUD", 0, 0, 1, 2, 3, 2, "", 2 }, + { "BUD", 1, 0, 1, 2, 4, 2, "T017,018,000", 2 }, + { "BUD", 2, 0, 1, 21, -1, 0, "", 2 }, + { "BUD", 3, 0, 1, 14, -1, 0, "", 2 }, + { "BUD", 4, 0, 1, 15, -1, 0, "", 2 }, + { "BUD", 5, 0, 1, 20, -1, 0, "", 2 }, + { "BUD", 6, 0, 1, 16, -1, 0, "", 2 }, + { "BUD", 7, 0, 1, 19, -1, 0, "", 2 }, + { "BUD", 8, 0, 1, 17, -1, 0, "", 2 }, + { "BUD", 9, 0, 1, 14, -1, 0, "T014,008,008,003,003,008,008,003,003,010,010,012,012,000", 2 }, + + { "LOU", 0, 0, 1, 2, 2, 3, "", 2 }, + { "LOU", 1, 0, 1, 2, 4, 2, "013,014,015,016,017,018,000", 2 }, + { "LOU", 2, 0, 1, 2, 4, 2, "018,017,016,015,014,013,000", 2 }, + + { "JIMMY", 0, 0, 16, 17, 2, 3, "", 17 }, + { "JIMMY", 1, 0, 16, 25, -1, 0, "", 17 }, + { "JIMMY", 2, 0, 16, 26, -1, 0, "", 17 }, + { "JIMMY", 3, 0, 16, 27, -1, 0, "", 17 }, + { "JIMMY", 4, 0, 16, 28, -1, 0, "", 17 }, + { "JIMMY", 5, 0, 16, 29, -1, 0, "", 17 }, + + { "TAMMY", 0, 0, 1, 2, 2, 3, "", 2 }, + { "TAMMY", 1, 0, 1, 2, 2, 3, "T008,008,009,009,008,008,009,009,008,008,009,009,002,000", 2 }, + { "TAMMY", 2, 0, 1, 2, 2, 3, "T002,010,010,010,002,000", 2 }, + { "TAMMY", 3, 0, 1, 2, 2, 3, "T011,011,011,011,011,002,000", 2 }, + { "TAMMY", 4, 0, 1, 2, 2, 3, "T013,014,015,013,014,015,013,009,001,000", 2 }, + + { "SKULL", 0, 0, 9, 9, 4, 0, "", 0 }, + { "SKULL", 1, 0, 1, 9, 4, 0, "001,002,003,004,005,006,007,008,009,000", 0 }, + { "SKULL", 2, 0, 1, 9, 4, 0, "009,008,007,006,005,004,003,002,001,000", 0 }, + + { "APE", 0, 0, 1, 6, 7, 0, "", 6 }, + { "APE", 1, 0, 1, 6, 7, 0, "002,001,000", 6 }, + { "APE", 2, 0, 1, 6, 7, 0, "002,003,001,000", 6 }, + { "APE", 3, 0, 1, 6, 7, 0, "004,005,004,005,004,001,000", 6 }, + { "APE", 4, 0, 1, 6, 7, 0, "001,003,005,004,005,004,001,000", 6 }, + + { "APE1", 0, 0, 15, 16, 7, 0, "", 16 }, + { "APE2", 0, 0, 14, 6, 7, 0, "", 6 }, + + { "SHOWERAM", 0, 0, 1, 2, 3, 0, "", 2 }, + { "SHOWERAM", 1, 0, 1, 2, 3, 0, "026,027,028,029,001,000", 2 }, + { "SHOWERAM", 2, 0, 1, 2, 3, 0, "001,029,028,027,026,000", 2 }, + + { "PRINCESS1", 0, 0, 19, 23, 2, 3, "", 23 }, + { "PRINCESS1", 1, 0, 19, 41, -1, 0, "", 23 }, + { "PRINCESS1", 2, 0, 19, 42, -1, 0, "", 23 }, + { "PRINCESS1", 3, 0, 19, 45, -1, 0, "", 23 }, + { "PRINCESS1", 4, 0, 19, 40, -1, 0, "", 23 }, + { "PRINCESS1", 5, 0, 19, 45, 2, 3, "T40,043,044,045,000", 45 }, + { "PRINCESS1", 6, 0, 19, 45, -1, 0, "T041,038,000", 38 }, + { "PRINCESS1", 7, 0, 22, 0, 0, 0, "", 0 }, + { "PRINCESS1", 8, 0, 19, 45, 2, 3, "T045,044,043,040,039,000", 39 }, + + { "PRINCESS2", 0, 0, 46, 23, 2, 3, "", 23 }, + { "PRINCESS2", 1, 0, 46, 29, 2, 3, "", 29 }, + { "PRINCESS2", 2, 0, 46, 29, 2, 3, "T029,036,035,000", 35 }, + + { "GUARDS", 0, 0, 7, 7, 0, 0, "", 7 }, + + { "AMGUARD", 0, 0, 19, 22, 2, 3, "", 22 }, + + { "MAN1", 0, 0, 2, 3, 2, 3, "", 3 }, + { "MAN2", 0, 0, 9, 10, 1, 2, "", 10 }, + + { "DOG", 0, 0, 6, 6, 1, 0, "", 0 }, + { "DOG", 1, 0, 6, 6, 1, 0, "010,009,008,000", 0 }, + { "DOG", 2, 0, 6, 6, 1, 0, "008,009,010,000", 0 }, + + { "CHEF", 0, 0, 5, 6, 2, 3, "", 6 }, + + { "HENRY", 0, 0, 7, 9, 2, 3, "", 9 }, + { "HENRY", 1, 0, 7, 21, -1, 0, "", 9 }, + { "HENRY", 2, 0, 7, 19, -1, 0, "", 9 }, + { "HENRY", 3, 0, 7, 20, -1, 0, "", 9 }, + { "HENRY", 4, 0, 8, 9, 2, 3, "", 9 }, + { "HENRY", 5, 0, 23, 9, -1, 0, "", 9 }, + { "HENRY", 6, 0, 7, 9, 2, 3, "T019,015,017,017,017,017,017,017,017,015,009,000", 9 }, + { "HENRY", 7, 0, 7, 9, 2, 3, "T018,010,000", 10 }, + { "HENRY", 8, 0, 7, 9, 2, 3, "T018,016,000", 16 }, + { "HENRY", 9, 0, 7, 9, 2, 3, "T018,011,000", 11 }, + { "HENRY", 10, 0, 29, 33, 1, 1, "", 33 }, + { "HENRY", 11, 0, 7, 30, 2, 0, "", 9 }, + { "HENRY", 12, 0, 7, 9, 2, 3, "025,026,000", 26 }, + { "HENRY", 13, 0, 7, 9, 2, 3, "027,028,027,028,000", 28 }, + { "HENRY", 14, 0, 7, 9, 2, 3, "026,025,007,000", 9 }, + + { "JOHAN", 0, 0, 1, 15, 2, 3, "", 15 }, + { "JOHAN", 1, 0, 1, 0, 0, 0, "T006,007,008,000", 15 }, + { "JOHAN", 2, 0, 1, 15, 2, 3, "T002,003,004,005,004,005,004,005,004,005,004,005,004,003,002,000", 15 }, + { "JOHAN", 3, 0, 1, 8, -1, 0, "", 15 }, + { "JOHAN", 4, 0, 1, 0, 0, 0, "T008,007,006,001,000", 15 }, + + { "KLUNK", 0, 0, 1, 2, 2, 3, "", 2 }, + { "KLUNK", 1, 0, 1, 2, 2, 3, "019,020,021,022,001,000", 2 }, + { "KLUNK", 2, 0, 1, 2, 2, 3, "001,022,021,020,019,016,517,000", 2 }, + { "KLUNK", 3, 0, 1, 2, 2, 3, "T010,011,010,011,010,011,009,000", 2 }, + + { "FRANK", 0, 0, 13, 14, 2, 3, "", 14 }, + { "FRANK", 1, 0, 13, 20, 0, 1, "", 14 }, + { "FRANK", 2, 0, 13, 14, 2, 3, "025,026,027,027,027,026,026,026,027,027,026,026,027,025,013,000", 14 }, + { "FRANK", 3, 0, 28, 14, 2, 3, "", 14 }, + + { "DEATH", 0, 0, 1, 2, 2, 3, "", 2 }, + { "DEATH", 1, 0, 1, 2, 2, 3, "013,014,015,016,017,001,000", 0 }, + { "DEATH", 2, 0, 1, 2, 2, 3, "001,017,016,015,014,013,000", 0 }, + { "DEATH", 3, 0, 1, 2, 2, 3, "T018,019,020,021,021,022,022,020,021,022,020,021,022,023,024,524,000", 2 }, + { "DEATH", 4, 0, 1, 2, 2, 3, "T025,026,027,028,028,028,028,028,028,028,028,028,029,035,000", 2 }, + { "DEATH", 5, 0, 1, 2, 2, 3, "T030,031,032,033,033,033,033,033,033,033,033,033,034,035,000", 2 }, + { "DEATH", 6, 0, 1, 2, 2, 3, "T023,022,020,019,018,001,000", 2 }, + + { "JASPAR", 0, 0, 1, 1, 22, 0, "026,027,028,029,028,029,028,029,030,023,000", 0 }, + { "JASPAR", 1, 0, 1, 1, 22, 0, "023,026,000", 0 }, + + { "ORACLE", 0, 0, 1, 5, 3, 0, "", 0 }, + + { "ZOMBIE", 0, 0, 1, 5, 2, 3, "", 5 }, + { "ZOMBIE", 1, 0, 1, 12, -1, 0, "", 5 }, + { "ZOMBIE", 2, 0, 1, 13, -1, 0, "", 5 }, + { "ZOMBIE", 3, 0, 1, 1, 5, 5, "", 5 }, + + { "ZOMBIE2", 0, 0, 14, 14, 0, 0, "", 0 }, + { "ZOMBIE3", 0, 0, 18, 18, 0, 0, "", 0 }, + + { "ANDERSON", 0, 0, 7, 8, 2, 3, "", 8 }, + { "ANDERSON", 1, 0, 7, 8, 1, 0, "", 8 }, + { "ANDERSON", 2, 0, 7, 16, -1, 0, "", 8 }, + { "ANDERSON", 3, 0, 7, 18, -1, 0, "", 8 }, + { "ANDERSON", 4, 0, 7, 19, -1, 0, "", 8 }, + { "ANDERSON", 5, 0, 7, 20, -1, 0, "", 8 }, + { "ANDERSON", 6, 0, 7, 21, 1, 0, "", 8 }, + + { "COMPY", 0, 0, 12, 12, -1, 0, "", 0 }, + { "COMPY", 1, 0, 10, 10, 10, 0, "010,011,012,012,013,014,014,000", 0 }, + { "COMPY", 2, 0, 10, 10, 10, 0, "014,013,012,000", 0 }, + + { "DEINO", 0, 0, 13, 13, -1, 0, "", 0 }, + { "DEINO", 1, 0, 9, 9, 9, 0, "009,010,000", 0 }, + + { "TMPD", 0, 0, 19, 22, 2, 3, "", 22 }, + + { "IAN", 0, 0, 7, 9, 2, 3, "", 9 }, + { "IAN", 1, 0, 8, 25, 3, 0, "", 25 }, + { "IAN", 2, 0, 7, 21, -1, 0, "", 9 }, + { "IAN", 3, 0, 7, 22, 1, 0, "", 9 }, + { "IAN", 4, 0, 7, 22, -1, 0, "", 9 }, + { "IAN", 5, 0, 7, 24, -1, 0, "", 9 }, + { "IAN", 6, 0, 7, 9, 2, 3, "034,034,034,035,035,036,036,035,035,036,035,036,035,000", 9 }, + { "IAN", 7, 0, 7, 31, -1, 0, "", 9 }, + + { "FAYE-H", 0, 0, 1, 1, 4, 1, "", 1 }, + { "FAYE-H", 1, 0, 1, 1, 4, 1, "007,000", 7 }, + { "FAYE-H", 2, 0, 1, 1, 4, 1, "009,010,011,009,001,000", 1 }, + { "FAYE-H", 3, 0, 1, 1, 4, 1, "E012,013,000", 1 }, + { "FAYE-H", 4, 0, 1, 1, 4, 1, "E015,000", 1 }, + { "FAYE-H", 5, 0, 1, 1, 4, 1, "E014,000", 1 }, + + { "AZURA-H", 0, 0, 1, 1, 4, 1, "", 1 }, + { "AZURA-H", 1, 0, 1, 1, 4, 1, "007,000", 7 }, + { "AZURA-H", 2, 0, 1, 1, 4, 1, "009,010,011,009,001,000", 1 }, + { "AZURA-H", 3, 0, 1, 1, 4, 1, "E012,013, 000", 1 }, + { "AZURA-H", 4, 0, 1, 1, 4, 1, "E015,000", 1 }, + { "AZURA-H", 5, 0, 1, 1, 4, 1, "E014,000", 1 }, + + { "FRANK-H", 0, 0, 1, 1, 4, 1, "", 1 }, + { "FRANK-H", 1, 0, 1, 1, 4, 1, "E009,000", 1 }, + { "FRANK-H", 2, 0, 1, 1, 4, 1, "E007,000", 1 }, + { "FRANK-H", 3, 0, 1, 1, 4, 1, "010,011,012,013,014,015,010,000", 1 }, + + { "JOE-E", 0, 0, 1, 2, 4, 1, "", 2 }, + { "JOE-E", 6, 0, 1, 2, 4, 1, "008,009,008,002,000", 2 }, + + { "AZURA-E", 0, 0, 1, 1, 5, 1, "", 1 }, + { "AZURA-E", 1, 0, 1, 1, 5, 1, "009,010,009,008,000", 1 }, + + { "FAYE-E", 0, 0, 1, 4, 4, 1, "", 1 }, + { "FAYE-E", 1, 0, 1, 4, 4, 1, "002,003,002,001,000", 1 }, + + { "ANDSON-E", 0, 0, 1, 3, 4, 1, "", 1 }, + { "ANDSON-E", 1, 0, 1, 3, 4, 1, "002,001,000", 1 }, + + { "JOE-H", 0, 0, 1, 1, 4, 4, "", 1 }, + { "JOE-H", 1, 0, 1, 1, 2, 3, "012,013,014,000", 14 }, + { "JOE-H", 2, 0, 1, 1, 2, 3, "010,011,000", 11 }, + { "JOE-H", 3, 0, 1, 1, 2, 3, "014,013,012,001,000", 1 }, + { "JOE-H", 4, 0, 1, 13, 1, 0, "", 13 }, + + { "RITA-H", 0, 0, 7, 1, 2, 3, "", 1 }, + { "RITA-H", 1, 0, 7, 0, 0, 0, "009,010,011,012,013,000", 13 }, + { "RITA-H", 2, 0, 7, 0, 0, 0, "014,015,016,000", 16 }, + { "RITA-H", 3, 0, 7, 0, 0, 0, "013,012,011,010,000", 10 }, + { "RITA-H", 4, 0, 7, 0, 0, 0, "009,007,008,007,009,000", 9 }, + { "RITA-H", 5, 0, 7, 0, 0, 0, "016,015,014,000", 14 }, + + { "RITA", 0, 0, 1, 4, 2, 3, "", 4 }, + { "RITA", 1, 0, 2, 4, 2, 3, "", 4 }, + + { "SPARKY-H", 0, 0, 1, 1, 2, 3, "", 1 }, + + { "HUGH", 0, 0, 1, 1, 2, 3, "", 1 }, + { "HUGH", 1, 0, 7, 7, 2, 3, "", 7 }, + + { "X2_JOE", 0, 0, 1, 1, 2, 3, "", 1 }, + { "X2_JOE", 1, 0, 1, 1, 2, 3, "001,007,008,008,007,001,000", 1 }, + + { "X2_RITA", 0, 0, 1, 1, 2, 3, "", 1 }, + { "X2_RITA", 1, 0, 1, 1, 2, 3, "001,007,008,008,007,001,000", 1 }, + + { "X3_RITA", 0, 0, 1, 1, 4, 1, "", 1 }, + { "X3_RITA", 1, 0, 1, 1, 4, 1, "007,000", 7 }, + { "X3_RITA", 2, 0, 1, 1, 4, 1, "009,010,011,009,001,000", 1 }, + { "X3_RITA", 3, 0, 1, 1, 4, 1, "E012,013,000", 1 }, + { "X3_RITA", 4, 0, 1, 1, 4, 1, "E015,000", 1 }, + { "X3_RITA", 5, 0, 1, 1, 4, 1, "E014,000", 1 }, + + { "X4_JOE", 0, 0, 1, 1, 3, 4, "", 1 }, + { "X4_JOE", 1, 0, 1, 13, 2, 3, "", 13 }, + { "X4_JOE", 2, 0, 1, 1, 3, 4, "009, 010, 011, 012, 013, 000", 13 }, + { "X4_JOE", 3, 0, 1, 1, 3, 4, "012, 011, 010, 009, 000", 9 }, + { "X4_JOE", 4, 0, 1, 1, 3, 4, "001, 019, 000", 19 }, + + { "X4_RITA", 0, 0, 1, 1, 0, 1, "", 1 }, + { "X4_RITA", 1, 0, 1, 7, 0, 1, "", 7 }, + { "X4_RITA", 2, 0, 1, 1, 3, 4, "004,005,006,006,006,006,007,000", 7 }, + { "X4_RITA", 3, 0, 1, 1, 3, 4, "005,004,001,000", 1 }, + { "X4_RITA", 4, 0, 1, 1, 3, 4, "001,003,000", 3 }, + + { "X5_SPARKY", 0, 0, 1, 1, 2, 3, "", 1 }, + { "X5_SPARKY", 1, 0, 1, 1, 2, 3, "001,010,011,011,001,000", 1 }, + { "X5_SPARKY", 2, 0, 1, 1, 2, 3, "001,007,008,009,000", 9 }, + + { "X6_HUGH", 0, 0, 1, 1, 2, 3, "", 1 }, + { "X6_HUGH", 1, 0, 1, 1, 2, 3, "007,007,007,007,,001,000", 1 }, + { "X6_HUGH", 2, 0, 1, 1, 2, 3, "008,008,008,008,008,009,009,008,008,008,009,008,000", 8 }, + + { "X10_JOE", 0, 0, 1, 2, 2, 3, "", 2 }, + { "X10_JOE", 1, 0, 1, 8, 2, 3, "", 8 }, + { "X10_JOE", 2, 0, 1, 2, 2, 3, "014,014,014,015,015,014,014,015,015,000", 2 }, + + { "X10_RITA", 0, 0, 1, 2, 2, 3, "", 2 }, + + { "X11_JOE", 0, 0, 1, 2, 0, 1, "", 2 }, + + { "X11_RITA", 0, 0, 1, 2, 0, 1, "", 2 }, + { "X11_RITA", 1, 0, 1, 2, 1, 0, "003,004,000", 4 }, + + { "JOHN", 0, 0, 1, 2, 2, 3, "", 1 }, + { "JOHN", 1, 0, 1, 15, -1, 0, "", 1 }, + { "JOHN", 2, 0, 1, 16, -1, 0, "", 1 }, + { "JOHN", 3, 0, 1, 17, -1, 0, "", 1 }, + + { "STEVE", 0, 0, 8, 2, 2, 3, "", 2 }, + { "STEVE", 1, 0, 8, 16, -1, 0, "", 2 }, + { "STEVE", 2, 0, 9, 18, -1, 0, "T016,017,017,016,008,000", 2 }, + { "STEVE", 3, 0, 8, 18, -1, 0, "", 2 }, + + { "TONY", 0, 0, 1, 2, 2, 3, "", 1 }, + { "TONY", 1, 0, 1, 12, -1, 0, "", 1 }, + + { "*", 0, 0, 0, 0, 0, 0, "", 0 } +}; +#endif + +} // End of namespace Queen + +#ifdef PALMOS_68K +#include "scumm_globals.h" + +_GINIT(Queen_Talk) +_GSETPTR(Queen::_speechParameters, GBVARS_SPEECHPARAMETERS_INDEX, Queen::Talk::SpeechParameters, GBVARS_QUEEN) +_GEND + +_GRELEASE(Queen_Talk) +_GRELEASEPTR(GBVARS_SPEECHPARAMETERS_INDEX, GBVARS_QUEEN) +_GEND + +#endif |