[Scummvm-cvs-logs] CVS: scummvm/saga actor.cpp,1.42,1.43 actor.h,1.22,1.23 console.cpp,1.20,1.21 console.h,1.7,1.8 input.cpp,1.24,1.25 resnames.h,1.13,1.14 saga.cpp,1.71,1.72 saga.h,1.47,1.48 script.cpp,1.33,1.34 script.h,1.29,1.30 sdebug.cpp,1.20,1.21 sfuncs.cpp,1.46,1.47 sthread.cpp,1.42,1.43 xref.txt,1.15,1.16

Andrew Kurushin h00ligan at users.sourceforge.net
Mon Dec 20 22:50:02 CET 2004


Update of /cvsroot/scummvm/scummvm/saga
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14053

Modified Files:
	actor.cpp actor.h console.cpp console.h input.cpp resnames.h 
	saga.cpp saga.h script.cpp script.h sdebug.cpp sfuncs.cpp 
	sthread.cpp xref.txt 
Log Message:
- rewritten actors speech engine :
  1) there are three types of speech: one acor, multiple actor, non actor
  2) slow speech implemented
  3) uses native engine flags (async,noanimate...) instead of semaphores  
- proper timings implemented
  

Index: actor.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/actor.cpp,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- actor.cpp	19 Dec 2004 13:38:11 -0000	1.42
+++ actor.cpp	21 Dec 2004 06:49:07 -0000	1.43
@@ -40,6 +40,7 @@
 #include "saga/actordata.h"
 #include "saga/stream.h"
 #include "saga/interface.h"
+#include "common/config-manager.h"
 
 namespace Saga {
 
@@ -62,6 +63,7 @@
 Actor::Actor(SagaEngine *vm) : _vm(vm) {
 	int i;
 	ActorData *actor;
+	debug(9, "Actor::Actor()");
 
 	// Get actor resource file context
 	_actorContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
@@ -73,7 +75,7 @@
 		actor = &_actors[i];
 		actor->actorId = ACTOR_INDEX_TO_ID(i);
 		actor->index = i;
-		debug(0, "init actorId=0x%X index=0x%X", actor->actorId, actor->index);
+		debug(9, "init actorId=0x%X index=0x%X", actor->actorId, actor->index);
 		actor->nameIndex = ActorTable[i].nameIndex;
 		actor->spriteListResourceId = ActorTable[i].spriteListResourceId;
 		actor->frameListResourceId = ActorTable[i].frameListResourceId;
@@ -100,7 +102,7 @@
 	int i;
 	ActorData *actor;
 
-	debug(0, "Actor::~Actor()");
+	debug(9, "Actor::~Actor()");
 	//release resources
 	for (i = 0; i < ACTORCOUNT; i++) {
 		actor = &_actors[i];
@@ -118,7 +120,7 @@
 	int i, orient;
 	int result;
 
-	debug(0, "Loading frame resource id 0x%X", actor->frameListResourceId);
+	debug(9, "Loading frame resource id 0x%X", actor->frameListResourceId);
 	result = RSC_LoadResource(_actorContext, actor->frameListResourceId, &resourcePointer, &resourceLength);
 	if (result != SUCCESS) {
 		warning("Couldn't load sprite action index resource");
@@ -126,7 +128,7 @@
 	}
 
 	framesCount = resourceLength / 16;
-	debug(0, "Frame resource contains %d frames", framesCount);
+	debug(9, "Frame resource contains %d frames", framesCount);
 	
 	framesPointer = (ActorFrame *)malloc(sizeof(ActorFrame) * framesCount);
 	if (framesPointer == NULL) {
@@ -154,7 +156,7 @@
 	actor->framesCount = framesCount;
 
 
-	debug(0, "Loading sprite resource id 0x%X", actor->spriteListResourceId);
+	debug(9, "Loading sprite resource id 0x%X", actor->spriteListResourceId);
 	if (_vm->_sprite->loadList(actor->spriteListResourceId, &actor->spriteList) != SUCCESS) {
 		warning("Unable to load sprite list");
 		return false;
@@ -163,7 +165,7 @@
 	i = _vm->_sprite->getListLen(actor->spriteList);
 
 	if ( (lastFrame >= i)) {
-		debug(0, "Appending to sprite list 0x%X", actor->spriteListResourceId);
+		debug(9, "Appending to sprite list 0x%X", actor->spriteListResourceId);
 		if (_vm->_sprite->appendList(actor->spriteListResourceId + 1, actor->spriteList) != SUCCESS) {
 			warning("Unable append sprite list");
 			return false;
@@ -199,6 +201,87 @@
 	}
 }
 
+void Actor::handleSpeech(int msec) {
+	int stringLength;
+	int sampleLength;
+	bool removeFirst;
+	int i;
+	int talkspeed;
+	ActorData *actor;
+
+	if (!isSpeaking()) return;
+
+	stringLength = strlen(_activeSpeech.strings[0]);
+
+	if (stringLength == 0)
+		error("Empty strings not allowed");
+
+	if (_vm->_script->_skipSpeeches) {
+		_activeSpeech.stringsCount = 0;
+		_vm->_sound->stopVoice();
+		_vm->_script->wakeUpThreads(kWaitTypeSpeech);
+		return;
+	}
+
+	if (!_activeSpeech.playing) {  // just added
+		talkspeed = ConfMan.getInt("talkspeed");
+		if (_activeSpeech.speechFlags & kSpeakSlow) {
+			if (_activeSpeech.slowModeCharIndex >= stringLength)
+				error("Wrong string index");
+
+			debug(0 , "Slow string!");
+			_activeSpeech.playingTime = 10 * talkspeed;
+			// 10 - fix it 
+
+		} else {
+			sampleLength = _vm->_sndRes->getVoiceLength(_activeSpeech.sampleResourceId); //fixme - too fast
+
+			if (sampleLength < 0) {
+				_activeSpeech.playingTime = stringLength * talkspeed;
+			} else {
+				_activeSpeech.playingTime = sampleLength;
+			}
+		}
+
+		if (_activeSpeech.sampleResourceId != -1)
+			_vm->_sndRes->playVoice(_activeSpeech.sampleResourceId);
+
+		if (_activeSpeech.actorIds[0] != 0) {
+			actor = getActor(_activeSpeech.actorIds[0]);
+			if (!(_activeSpeech.speechFlags & kSpeakNoAnimate)) {
+				actor->currentAction = kActionSpeak;
+				//a->actionCycle = rand() % 64; todo
+			}
+		}
+		_activeSpeech.playing = true;			
+		return;
+	}
+
+
+	_activeSpeech.playingTime -= msec;
+
+	removeFirst = false;
+	if (_activeSpeech.playingTime <= 0) {
+		if (_activeSpeech.speechFlags & kSpeakSlow) {
+			_activeSpeech.slowModeCharIndex++;
+			if (_activeSpeech.slowModeCharIndex >= stringLength)
+				removeFirst = true;
+		} else {
+			removeFirst = true;
+		}		
+	}
+
+	if (removeFirst) {
+		for (i = 1; i < _activeSpeech.stringsCount; i++) {
+			_activeSpeech.strings[i - 1] = _activeSpeech.strings[i];
+		}
+		_activeSpeech.stringsCount--;
+	}
+
+	if (!isSpeaking())
+		_vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, ticksToMSec(kScriptTimeTicksPerSecond / 3));
+}
+
 int Actor::direct(int msec) {
 	int i;
 	ActorData *actor;
@@ -228,13 +311,6 @@
 					handleWalkIntent(actor, &a_intent->walkIntent, &a_intent->a_idone, msec);
 				}
 				break;
-			case INTENT_SPEAK:
-				// Actor wants to blab
-				{
-					handleSpeakIntent(actor, a_intent, &a_intent->a_idone, msec);
-				}
-				break;
-
 			default:
 				break;
 			}
@@ -275,6 +351,8 @@
 		}
 	}
 
+//process speech
+	handleSpeech(msec);
 	return SUCCESS;
 }
 
@@ -284,7 +362,7 @@
 	ActorData *actor;
 
 	_drawOrderList.clear();
-	for (i = 0;i < ACTORCOUNT;i++) {
+	for (i = 0; i < ACTORCOUNT; i++) {
 		actor = &_actors[i];
 		if (actor->disabled) continue;
 		if (actor->sceneNumber != _vm->_scene->currentSceneNumber()) continue;
@@ -318,16 +396,10 @@
 	ActorOrderList::iterator actorDrawOrderIterator;
 	ActorData *actor;
 
-	ActorIntentList::iterator actorIntentIterator;
-	ACTORINTENT *a_intent;
-
-	ActorDialogList::iterator actorDialogIterator;
-	ACTORDIALOGUE *a_dialogue;
 
 	int o_idx; //Orientation index
 	int sprite_num;
 
-	int diag_x, diag_y; // dialog coordinates
 
 	SURFACE *back_buf;
 
@@ -350,198 +422,54 @@
 			continue;
 		}
 		_vm->_sprite->drawOccluded(back_buf, actor->spriteList, sprite_num, actor->screenPosition, actor->screenScale, actor->screenDepth);
-
-		// If actor's current intent is to speak, oblige him by 
-		// displaying his dialogue 
-		actorIntentIterator = actor->a_intentlist.begin();
-		if (actorIntentIterator != actor->a_intentlist.end()) {
-			a_intent = actorIntentIterator.operator->();
-			if (a_intent->a_itype == INTENT_SPEAK) {
-				actorDialogIterator = a_intent->si_diaglist.begin();
-				if (actorDialogIterator != a_intent->si_diaglist.end()) {
-					a_dialogue = actorDialogIterator.operator->();
-					diag_x = actor->screenPosition.x;
-					diag_y = actor->screenPosition.y;
-					diag_y -= ACTOR_DIALOGUE_HEIGHT;
-					_vm->textDraw(MEDIUM_FONT_ID, back_buf, a_dialogue->d_string, diag_x, diag_y, actor->speechColor, 0,
-								FONT_OUTLINE | FONT_CENTERED);
-				}
-			}
-		}
 	}
 
-	return SUCCESS;
-}
-
-// Called if the user wishes to skip a line of dialogue (spacebar in the 
-// original game). Will find all actors currently talking and remove one
-// dialogue entry if there is a current speak intent present.
-
-int Actor::skipDialogue() {
-	int i;
-	ActorData *actor;
-
-	ActorIntentList::iterator actorIntentIterator;
-	ACTORINTENT *a_intent;
-
-	ActorDialogList::iterator actorDialogIterator;
-	ACTORDIALOGUE *a_dialogue;
-
-	for (i = 0; i < ACTORCOUNT; i++) {
-		actor = &_actors[i];
-		if (actor->disabled) continue;
-		// Check the actor's current intent for a speak intent
-		actorIntentIterator = actor->a_intentlist.begin();
-		if (actorIntentIterator != actor->a_intentlist.end()) {
-			a_intent = actorIntentIterator.operator->();
-			if (a_intent->a_itype == INTENT_SPEAK) {
-				// Okay, found a speak intent. Remove one dialogue entry 
-				// from it, releasing any semaphore */
-				actorDialogIterator = a_intent->si_diaglist.begin();
-				if (actorDialogIterator != a_intent->si_diaglist.end()) {
-					a_dialogue = actorDialogIterator.operator->();
-					if (a_dialogue->d_sem != NULL) {
-						_vm->_script->SThreadReleaseSem(a_dialogue->d_sem);
-					}
-					a_intent->si_diaglist.erase(actorDialogIterator);
-					// And stop any currently playing voices
-					_vm->_sound->stopVoice();
-				}
-			}
-		}
-	}
-
-	return SUCCESS;
-}
-
-void Actor::speak(uint16 actorId, const char *d_string, uint16 d_voice_rn, SEMAPHORE *sem) {
-	ActorData *actor;
-	ActorIntentList::iterator actorIntentIterator;
-	ACTORINTENT *a_intent_p = NULL;
-	ACTORINTENT a_intent;
-	int use_existing_ai = 0;
-	ACTORDIALOGUE a_dialogue;
-
-	a_dialogue.d_string = d_string;
-	a_dialogue.d_voice_rn = d_voice_rn;
-	a_dialogue.d_time = getSpeechTime(d_string, d_voice_rn);
-	a_dialogue.d_sem_held = 1;
-	a_dialogue.d_sem = sem;
-
-	actor = getActor(actorId);
-
-	// If actor's last registered intent is to speak, we can queue the
-	// requested dialogue on that intent context; so examine the last
-	// intent
+// draw speeches
+	if (isSpeaking() && !_vm->_script->_skipSpeeches) {
+		int i;
+		int textDrawFlags, speechColor;
+		Point speechCoord;
+		char oneChar[2];
+		oneChar[1] = 0;
+		const char *outputString;
 
-	actorIntentIterator = actor->a_intentlist.end();
-	--actorIntentIterator;
-	if (actorIntentIterator != actor->a_intentlist.end()) {
-		a_intent_p = actorIntentIterator.operator->();
-		if (a_intent_p->a_itype == INTENT_SPEAK) {
-			use_existing_ai = 1;
+		if (_activeSpeech.speechFlags & kSpeakSlow) {
+			outputString = oneChar;
+			oneChar[0] = _activeSpeech.strings[0][_activeSpeech.slowModeCharIndex];
+		} else {
+			outputString = _activeSpeech.strings[0];
 		}
-	}
-
-	if (use_existing_ai) {
-		// Store the current dialogue off the existing actor intent
-		a_intent_p->si_diaglist.push_back(a_dialogue);
-	} else {
-		// Create a new actor intent
-		a_intent.a_itype = INTENT_SPEAK;
-		a_intent.a_idone = 0;
-		a_intent.a_iflags = 0;
-
-		a_intent.si_last_action = actor->action;
-		a_intent.si_diaglist.push_back(a_dialogue);
-
-		actor->a_intentlist.push_back(a_intent);
-	}
-
-	if (sem != NULL) {
-		_vm->_script->SThreadHoldSem(sem);
-	}
-}
-
-int Actor::handleSpeakIntent(ActorData *actor, ACTORINTENT *a_aintent, int *complete_p, int msec) {
-	ActorDialogList::iterator actorDialogIterator;
-	ActorDialogList::iterator nextActorDialogIterator;
-	ACTORDIALOGUE *a_dialogue;
-	ACTORDIALOGUE *a_dialogue2;
-	long carry_time;
-	int intent_complete = 0;
-
-	if (!a_aintent->si_init) {
-		// Initialize speak intent by setting up action
-		actor->action = ACTION_SPEAK;
-		actor->action_frame = 0;
-		actor->action_time = 0;
-		actor->action_flags = ACTION_LOOP;
-		a_aintent->si_init = 1;
-	}
 
-	// Process actor dialogue list
-	actorDialogIterator = a_aintent->si_diaglist.begin();
-	if (actorDialogIterator != a_aintent->si_diaglist.end()) {
-		a_dialogue = actorDialogIterator.operator->();
-		if (!a_dialogue->d_playing) {
-			// Dialogue voice hasn't played yet - play it now
-			_vm->_sndRes->playVoice(a_dialogue->d_voice_rn);
-			a_dialogue->d_playing = 1;
+		textDrawFlags = FONT_CENTERED;
+		if (_activeSpeech.outlineColor != 0) {
+			textDrawFlags |= FONT_OUTLINE;
 		}
 
-		a_dialogue->d_time -= msec;
-		if (a_dialogue->d_time <= 0) {
-			// Dialogue time has expired; carry negative time to next
-			// dialogue entry if present, release any semaphores and
-			// delete the expired entry
-
-			//actor->action = ACTION_IDLE;
-
-			if (a_dialogue->d_sem != NULL) {
-				_vm->_script->SThreadReleaseSem(a_dialogue->d_sem);
-			}
-
-			carry_time = a_dialogue->d_time;
+		if (_activeSpeech.actorIds[0] != 0) {
+			
+			for (i = 0; i < _activeSpeech.actorsCount; i++){
+				actor = getActor(_activeSpeech.actorIds[i]);
+				speechCoord.x = actor->screenPosition.x;
+				speechCoord.y = actor->screenPosition.y;
+				speechCoord.y -= ACTOR_DIALOGUE_HEIGHT;
+				if (_activeSpeech.actorsCount > 1)
+					speechColor = actor->speechColor;
+				else
+					speechColor = _activeSpeech.speechColor;
 
-			nextActorDialogIterator = actorDialogIterator;
-			++nextActorDialogIterator;
-			if (nextActorDialogIterator != a_aintent->si_diaglist.end()) {
-				a_dialogue2 = nextActorDialogIterator.operator->();
-				a_dialogue2->d_time -= carry_time;
+				_vm->textDraw(MEDIUM_FONT_ID, back_buf, outputString, speechCoord.x, speechCoord.y, speechColor, _activeSpeech.outlineColor, textDrawFlags);
 			}
 
-			// Check if there are any dialogue nodes left. If not, 
-			// flag this speech intent as complete
-
-			actorDialogIterator = a_aintent->si_diaglist.erase(actorDialogIterator);
-			if (actorDialogIterator == a_aintent->si_diaglist.end()) {
-				intent_complete = 1;
-			}
+		} else { // non actors speech
+			warning("non actors speech occures");
+			//todo: write it
 		}
-	} else {
-		intent_complete = 1;
-	}
 
-	if (intent_complete) {
-		*complete_p = 1;
 	}
 
 	return SUCCESS;
 }
 
-int Actor::getSpeechTime(const char *d_string, uint16 d_voice_rn) {
-	int voice_len;
-
-	voice_len = _vm->_sndRes->getVoiceLength(d_voice_rn);
-
-	if (voice_len < 0) {
-		voice_len = strlen(d_string) * ACTOR_DIALOGUE_LETTERTIME;
-	}
-
-	return voice_len;
-}
-
 void Actor::setOrientation(uint16 actorId, int orient) {
 	ActorData *actor;
 	
@@ -605,7 +533,7 @@
 
 	actor->a_intentlist.push_back(actor_intent);
 	int is = actor->a_intentlist.size();
-	debug(0, "actor->a_intentlist.size() %i", is);
+	debug(9, "actor->a_intentlist.size() %i", is);
 
 	if (sem != NULL) {
 		_vm->_script->SThreadHoldSem(sem);
@@ -794,12 +722,80 @@
 	actor->actorY += movePoint.y;
 }
 
-
 void Actor::StoA(Point &actorPoint, const Point &screenPoint) {
 	actorPoint.x = (screenPoint.x * ACTOR_LMULT);
 	actorPoint.y = (screenPoint.y * ACTOR_LMULT);
 }
 
+void Actor::actorSpeech(uint16 actorId, const char **strings, int stringsCount, uint16 sampleResourceId, int speechFlags) {
+	ActorData *actor;
+	int i;
+
+	actor = getActor(actorId);
+	for (i = 0; i < stringsCount; i++) {		
+		_activeSpeech.strings[i] = strings[i];
+	}
+	_activeSpeech.stringsCount = stringsCount;
+	_activeSpeech.speechFlags = speechFlags;
+	_activeSpeech.actorsCount = 1;
+	_activeSpeech.actorIds[0] = actorId;
+	_activeSpeech.speechColor = actor->speechColor;
+	_activeSpeech.outlineColor = 15; // fixme - BLACK
+	_activeSpeech.sampleResourceId = sampleResourceId;
+	_activeSpeech.playing = false;
+	_activeSpeech.slowModeCharIndex = 0;
+}
+
+void Actor::nonActorSpeech(const char **strings, int stringsCount, int speechFlags) {
+	int i;
+	
+	_vm->_script->wakeUpThreads(kWaitTypeSpeech);
+
+	for (i = 0; i < stringsCount; i++) {		
+		_activeSpeech.strings[i] = strings[i];
+	}
+	_activeSpeech.stringsCount = stringsCount;
+	_activeSpeech.speechFlags = speechFlags;
+	_activeSpeech.actorsCount = 1;
+	_activeSpeech.actorIds[0] = 0;
+	//_activeSpeech.speechColor = ;
+	//_activeSpeech.outlineColor = ; 
+	_activeSpeech.sampleResourceId = -1;
+	_activeSpeech.playing = false;
+	_activeSpeech.slowModeCharIndex = 0;
+}
+
+void Actor::simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags) {
+	int i;
+
+	for (i = 0; i < actorIdsCount; i++) {		
+		_activeSpeech.actorIds[i] = actorIds[i];
+	}
+	_activeSpeech.strings[0] = string;
+	_activeSpeech.stringsCount = 1;
+	_activeSpeech.speechFlags = speechFlags;
+	//_activeSpeech.speechColor = ; // get's from every actor 
+	_activeSpeech.outlineColor = 0; // disable outline 
+	_activeSpeech.sampleResourceId = -1;
+	_activeSpeech.playing = false;
+	_activeSpeech.slowModeCharIndex = 0;
+	
+	// caller should call thread->wait(kWaitTypeSpeech) by itself
+}
+
+void Actor::abortAllSpeeches() {
+	if (_vm->_script->_abortEnabled)
+		_vm->_script->_skipSpeeches = true;
+
+	for (int i = 0; i < 10; i++)
+		_vm->_script->executeThreads(0);
+}
+
+void Actor::abortSpeech() {
+	_vm->_sound->stopVoice();
+	_activeSpeech.playingTime = 0;
+}
+
 // Console wrappers - must be safe to run
 // TODO - checkup ALL arguments, cause wrong arguments may fall function with "error"
 

Index: actor.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/actor.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- actor.h	19 Dec 2004 13:38:11 -0000	1.22
+++ actor.h	21 Dec 2004 06:49:07 -0000	1.23
@@ -39,22 +39,46 @@
 
 #define ACTOR_ACTIONTIME 80
 
-#define ACTOR_DIALOGUE_LETTERTIME 50
 #define ACTOR_DIALOGUE_HEIGHT 100
 
 #define ACTOR_LMULT 4
 
 #define ACTOR_ORIENTATION_COUNT 4
 
+#define ACTOR_SPEECH_STRING_MAX 16
+#define ACTOR_SPEECH_ACTORS_MAX 8
+
 #define IS_VALID_ACTOR_INDEX(index) ((index >= 0) && (index < ACTORCOUNT))
 #define IS_VALID_ACTOR_ID(id) ((id == 1) || (id >= 0x2000) && (id < (0x2000 | ACTORCOUNT)))
 #define ACTOR_ID_TO_INDEX(id) ((((uint16)id) == 1 ) ? 0 : (int)(((uint16)id) & ~0x2000))
 #define ACTOR_INDEX_TO_ID(index) ((((int)index) == 0 ) ? 1 : (uint16)(((int)index) | 0x2000))
 
+
+enum ActorActions {
+	kActionWait = 0,
+	kActionWalkToPoint = 1,
+	kActionWalkToLink = 2,
+	kActionWalkDir = 3,
+	kActionSpeak = 4,
+	kActionAccept = 5,
+	kActionStoop = 6,
+	kActionLook = 7,
+	kActionCycleFrames = 8,
+	kActionPongFrames = 9,
+	kActionFreeze = 10,
+	kActionFall = 11,
+	kActionClimb = 12
+};
+
+enum SpeechFlags {
+	kSpeakNoAnimate = 1,
+	kSpeakAsync = 2,
+	kSpeakSlow = 4
+};
+
 enum ACTOR_INTENTS {
 	INTENT_NONE = 0,
-	INTENT_PATH = 1,
-	INTENT_SPEAK = 2
+	INTENT_PATH = 1
 };
 
 enum ACTOR_WALKFLAGS {
@@ -136,17 +160,6 @@
 };
 
 
-struct ACTORDIALOGUE {
-	int d_playing;
-	const char *d_string;
-	uint16 d_voice_rn;
-	long d_time;
-	int d_sem_held;
-	SEMAPHORE *d_sem;
-	ACTORDIALOGUE() { memset(this, 0, sizeof(*this)); }
-};
-
-typedef Common::List<ACTORDIALOGUE> ActorDialogList;
 
 
 struct ACTORINTENT {
@@ -154,34 +167,27 @@
 	uint16 a_iflags;
 	int a_idone;
 
-	int si_init;
-	uint16 si_flags;
-	int si_last_action;
-	ActorDialogList si_diaglist;	/* Actor dialogue list */
-
 	WALKINTENT walkIntent;
 
 	ACTORINTENT() {
 		a_itype = 0;
 		a_iflags = 0;
 		a_idone = 0;
-
-		si_init = 0;
-		si_flags = 0;
-		si_last_action = 0;
 	}
 };
 
 typedef Common::List<ACTORINTENT> ActorIntentList;
 
+
 struct ActorData {
 	bool disabled;				// Actor disabled in init section
 	int index;					// Actor index
 	uint16 actorId;				// Actor id
 	int nameIndex;				// Actor's index in actor name string list
 	byte speechColor;			// Actor dialogue color
-	uint16 flags;				// Actor flags
+	uint16 flags;				// Actor initial flags
 	
+
 	int sceneNumber;			// scene of actor
 	int actorX;					// Actor's logical coordinates
 	int actorY;					// 
@@ -191,9 +197,12 @@
 	int screenDepth;			//
 	int screenScale;			//
 
-	int currentAction;		
-	int facingDirection;
+	uint16 actorFlags;			// dynamic flags
+	int currentAction;			// ActorActions type
+	int facingDirection;		// orientation
 	int actionDirection;
+	int actionCycle;
+	int frameNumber;			// current actor frame number
 	
 	SPRITELIST *spriteList;		// Actor's sprite list data
 	int spriteListResourceId;	// Actor's sprite list resource id
@@ -233,9 +242,6 @@
 		index = 0;
 		actorId = 0;
 		nameIndex = 0;
-		currentAction = 0;
-		facingDirection = 0;
-		actionDirection = 0;
 		speechColor = 0;
 		frames = NULL;
 		framesCount = 0;
@@ -248,6 +254,11 @@
 		actorY = 0;
 		actorZ = 0;
 		screenDepth = 0;
+		
+		actorFlags = 0;
+		currentAction = 0;
+		facingDirection = 0;
+		actionDirection = 0;
 
 		idle_time = 0;
 		orient = 0;
@@ -270,6 +281,24 @@
 	int time;
 };
 
+struct SpeechData {
+	int speechColor;
+	int outlineColor;
+	int speechFlags;
+	const char *strings[ACTOR_SPEECH_STRING_MAX];
+	int stringsCount;
+	int slowModeCharIndex;
+	uint16 actorIds[ACTOR_SPEECH_ACTORS_MAX];
+	int actorsCount;
+	int sampleResourceId;
+	bool playing;
+	int playingTime;
+
+	SpeechData() { 
+		memset(this, 0, sizeof(*this)); 
+	}
+};
+
 class Actor {
 public:
 	Actor(SagaEngine *vm);
@@ -284,7 +313,6 @@
 	int drawActors();
 	void updateActorsScene();			// calls from scene loading to update Actors info
 
-	void AtoS(Point &screenPoint, const Point &actorPoint);
 	void StoA(Point &actorPoint, const Point &screenPoint);
 
 	void move(uint16 actorId, const Point &movePoint);
@@ -292,15 +320,25 @@
 
 	void walkTo(uint16 actorId, const Point *walk_pt, uint16 flags, SEMAPHORE *sem);
 		
-	void speak(uint16 actorId, const char *d_string, uint16 d_voice_rn, SEMAPHORE *sem);
 	
-	int skipDialogue();
 	
-	int getSpeechTime(const char *d_string, uint16 d_voice_rn);
 	void setOrientation(uint16 actorId, int orient);
 	void setAction(uint16 actorId, int action_n, uint16 action_flags);
 	void setDefaultAction(uint16 actorId, int action_n, uint16 action_flags);
 
+//	speech 
+	void actorSpeech(uint16 actorId, const char **strings, int stringsCount, uint16 sampleResourceId, int speechFlags);
+	void nonActorSpeech(const char **strings, int stringsCount, int speechFlags);
+	void simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, int speechFlags);
+	void setSpeechColor(int speechColor, int outlineColor) {
+		_activeSpeech.speechColor = speechColor;
+		_activeSpeech.outlineColor = outlineColor;
+	}
+	void abortAllSpeeches();
+	void abortSpeech();
+	bool isSpeaking() {
+		return _activeSpeech.stringsCount > 0;
+	}
 	
 private:
 	int handleWalkIntent(ActorData *actor, WALKINTENT *a_walk_int, int *complete_p, int msec);
@@ -308,15 +346,16 @@
 	int setPathNode(WALKINTENT *walk_int, const Point &src_pt, Point *dst_pt, SEMAPHORE *sem);
 
 	ActorData *getActor(uint16 actorId);
-
 	bool loadActorResources(ActorData * actor);
 	
 	void createDrawOrderList();
+	void handleSpeech(int msec);
 
 	SagaEngine *_vm;
 	RSCFILE_CONTEXT *_actorContext;
 	ActorOrderList _drawOrderList;
 	ActorData _actors[ACTORCOUNT];
+	SpeechData _activeSpeech;
 };
 
 } // End of namespace Saga

Index: console.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/console.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- console.cpp	17 Dec 2004 20:38:16 -0000	1.20
+++ console.cpp	21 Dec 2004 06:49:07 -0000	1.21
@@ -86,6 +86,21 @@
 Console::~Console() {
 }
 
+int Console::DebugPrintf(const char *format, ...) {
+	int count;
+	va_list	argptr;
+
+	va_start(argptr, format);
+	
+	debug(1, format, argptr);
+	count = Common::Debugger<Console>::DebugPrintf(format);
+	
+	va_end (argptr);
+
+	return count;
+}
+
+
 void Console::preEnter() {
 }
 

Index: console.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/console.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- console.h	17 Dec 2004 20:38:16 -0000	1.7
+++ console.h	21 Dec 2004 06:49:07 -0000	1.8
@@ -35,6 +35,8 @@
 	Console(SagaEngine *vm);
 	~Console(void);
 
+	int DebugPrintf(const char *format, ...);
+
 protected:
 	virtual void preEnter();
 	virtual void postEnter();

Index: input.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/input.cpp,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- input.cpp	5 Dec 2004 17:42:18 -0000	1.24
+++ input.cpp	21 Dec 2004 06:49:07 -0000	1.25
@@ -71,7 +71,7 @@
 
 			// Actual game keys
 			case 32: // space
-				_actor->skipDialogue();
+				_actor->abortSpeech();
 				break;
 			case 19:  // pause
 			case 'p':
@@ -80,7 +80,7 @@
 			case 27: // Esc
 				// Skip to next scene skip target
 				if (!_interface->getMode() == kPanelNone) // FIXME: hack
-					_script->SThreadAbortAll();
+					_actor->abortAllSpeeches();
 				else
 					_scene->skipScene();
 				break;

Index: resnames.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/resnames.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- resnames.h	18 Dec 2004 16:08:59 -0000	1.13
+++ resnames.h	21 Dec 2004 06:49:07 -0000	1.14
@@ -104,6 +104,11 @@
 #define CAVE_VOICE_12 12
 #define CAVE_VOICE_13 13
 
+#define SCENE1_VOICE_009 57
+//TODO: fill it
+#define SCENE1_VOICE_138 186
+
+
 // MUSIC
 #define MUSIC_1 9
 #define MUSIC_2 10

Index: saga.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/saga.cpp,v
retrieving revision 1.71
retrieving revision 1.72
diff -u -d -r1.71 -r1.72
--- saga.cpp	3 Dec 2004 19:15:44 -0000	1.71
+++ saga.cpp	21 Dec 2004 06:49:07 -0000	1.72
@@ -248,7 +248,7 @@
 			}
 			_actor->direct(msec);
 			_events->handleEvents(msec);
-			_script->SThreadExecThreads(msec);
+			_script->executeThreads(msec);
 		}
 		// Per frame processing
 		_render->drawScene();

Index: saga.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/saga.h,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- saga.h	15 Dec 2004 00:24:11 -0000	1.47
+++ saga.h	21 Dec 2004 06:49:07 -0000	1.48
@@ -74,15 +74,22 @@
 
 enum SAGAGameId {
 	GID_ITE,
-	GID_ITECD,
 	GID_IHNM
 };
 
+enum scriptTimings {
+	kScriptTimeTicksPerSecond = (728L/10L),
+};
+
 struct CLICKAREA {
 	int n_points;
 	Point *points;
 };
 
+inline int ticksToMSec(int tick) {
+	return tick * 1000 / kScriptTimeTicksPerSecond;
+}
+
 class SagaEngine : public Engine {
 	void errorString(const char *buf_input, char *buf_output);
 

Index: script.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/script.cpp,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -d -r1.33 -r1.34
--- script.cpp	15 Dec 2004 00:24:11 -0000	1.33
+++ script.cpp	21 Dec 2004 06:49:07 -0000	1.34
@@ -148,9 +148,9 @@
 	byte *bytecode_p;
 	size_t bytecode_len;
 	uint32 scriptl_rn;
-	byte *diagl_p;
-	size_t diagl_len;
-	uint32 diagl_rn;
+	byte *stringsPointer;
+	size_t stringsLength;
+	uint32 stringsResourceId;
 	byte *voicelut_p;
 	size_t voicelut_len;
 	uint32 voicelut_rn;
@@ -174,14 +174,13 @@
 
 	script_data = (SCRIPTDATA *)malloc(sizeof *script_data);
 	if (script_data == NULL) {
-		warning("Memory allocation failed");
-		return MEM;
+		error("Memory allocation failed");
 	}
 
 	script_data->loaded = 0;
 
 	// Initialize script pointers
-	script_data->diag = NULL;
+	script_data->strings = NULL;
 	script_data->bytecode = NULL;
 	script_data->voice = NULL;
 
@@ -198,34 +197,21 @@
 	script_data->bytecode = loadBytecode(bytecode_p, bytecode_len);
 
 	if (script_data->bytecode == NULL) {
-		warning("Error interpreting script bytecode resource");
-		free(script_data);
-		RSC_FreeResource(bytecode_p);
-		return FAILURE;
+		error("Error interpreting script bytecode resource");
 	}
 
-	// Load script dialogue list
-	diagl_rn = _scriptLUT[script_num].diag_list_rn;
-
-	// Load dialogue list resource
-	result = RSC_LoadResource(_scriptContext, diagl_rn, &diagl_p, &diagl_len);
-	if (result != SUCCESS) {
-		warning("Error loading dialogue list resource");
-		free(script_data);
-		RSC_FreeResource(bytecode_p);
-		return FAILURE;
-	}
+	// Load script strings list
+	stringsResourceId = _scriptLUT[script_num].diag_list_rn;
 
-	// Convert dialogue list resource to logical dialogue list
-	script_data->diag = loadDialogue(diagl_p, diagl_len);
-	if (script_data->diag == NULL) {
-		warning("Error interpreting dialogue list resource");
-		free(script_data);
-		RSC_FreeResource(bytecode_p);
-		RSC_FreeResource(diagl_p);
-		return FAILURE;
+	// Load strings list resource
+	result = RSC_LoadResource(_scriptContext, stringsResourceId, &stringsPointer, &stringsLength);
+	if ((result != SUCCESS) || (stringsLength == 0)) {
+		error("Error loading strings list resource");
 	}
-
+	
+	// Convert strings list resource to logical strings list
+	loadStrings(stringsPointer, stringsLength, script_data->strings);
+	
 	// Load voice resource lookup table
 	if (_voiceLUTPresent) {
 		voicelut_rn = _scriptLUT[script_num].voice_lut_rn;
@@ -233,22 +219,13 @@
 		// Load voice LUT resource
 		result = RSC_LoadResource(_scriptContext, voicelut_rn, &voicelut_p, &voicelut_len);
 		if (result != SUCCESS) {
-			warning("Error loading voice LUT resource");
-			free(script_data);
-			RSC_FreeResource(bytecode_p);
-			RSC_FreeResource(diagl_p);
-			return FAILURE;
+			error("Error loading voice LUT resource");
 		}
 
 		// Convert voice LUT resource to logical voice LUT
 		script_data->voice = loadVoiceLUT(voicelut_p, voicelut_len, script_data);
 		if (script_data->voice == NULL) {
-			warning("Error interpreting voice LUT resource");
-			free(script_data);
-			RSC_FreeResource(bytecode_p);
-			RSC_FreeResource(diagl_p);
-			RSC_FreeResource(voicelut_p);
-			return FAILURE;
+			error("Error interpreting voice LUT resource");
 		}
 	}
 
@@ -272,11 +249,10 @@
 	debug(0, "Releasing script data.");
 
 	// Finish initialization
-	if (_currentScript->diag != NULL) {
-		free(_currentScript->diag->str);
-		free(_currentScript->diag->str_off);
+	if (_currentScript->strings != NULL) {
+		free(_currentScript->strings->strings);
 	}
-	free(_currentScript->diag);
+	free(_currentScript->strings);
 
 	if (_currentScript->bytecode != NULL) {
 		free(_currentScript->bytecode->entrypoints);
@@ -376,66 +352,54 @@
 	return bc_new_data;
 }
 
-// Reads a logical dialogue list from a dialogue list resource in memory.
+const char *Script::getString(int index) {
+	if (_currentScript->strings->stringsCount <= index)
+		error("Script::getString wrong index 0x%X", index);
+	return _currentScript->strings->strings[index];
+}
+
+// Reads a logical strings list from a strings list resource in memory.
 // Returns NULL on failure.
-DIALOGUE_LIST *Script::loadDialogue(const byte *dialogue_p, size_t dialogue_len) {
-	DIALOGUE_LIST *dialogue_list;
-	uint16 n_dialogue;
+void Script::loadStrings(const byte *stringsPointer, size_t stringsLength, StringsList *&strings) {
+	uint16 stringsCount;
 	uint16 i;
 	size_t offset;
 
-	debug(0, "Loading dialogue list...");
+	debug(9, "Loading strings list...");
 
 	// Allocate dialogue list structure
-	dialogue_list = (DIALOGUE_LIST *)malloc(sizeof *dialogue_list);
-	if (dialogue_list == NULL) {
-		return NULL;
+	strings = (StringsList *)malloc(sizeof *strings);
+	if (strings == NULL) {
+		error("No enough memory for strings list");
 	}
 
-	MemoryReadStreamEndian scriptS(dialogue_p, dialogue_len, IS_BIG_ENDIAN);
+	MemoryReadStreamEndian scriptS(stringsPointer, stringsLength, IS_BIG_ENDIAN);
 
 	// First uint16 is the offset of the first string
 	offset = scriptS.readUint16();
-	if (offset > dialogue_len) {
-		warning("Error, invalid string offset");
-		return NULL;
+	if (offset > stringsLength) {
+		error("Invalid string offset");
 	}
 
 	// Calculate table length
-	n_dialogue = offset / 2;
-	dialogue_list->n_dialogue = n_dialogue;
+	stringsCount = offset / 2;
+	strings->stringsCount = stringsCount;
 
 	// Allocate table of string pointers
-	dialogue_list->str = (const char **)malloc(n_dialogue * sizeof(const char *));
-	if (dialogue_list->str == NULL) {
-		free(dialogue_list);
-		return NULL;
-	}
-
-	// Allocate table of string offsets
-	dialogue_list->str_off = (size_t *)malloc(n_dialogue * sizeof(size_t));
-	if (dialogue_list->str_off == NULL) {
-		free(dialogue_list->str);
-		free(dialogue_list);
-		return NULL;
+	strings->strings = (const char **)malloc(stringsCount * sizeof(const char *));
+	if (strings->strings == NULL) {
+		error("No enough memory for strings list");
 	}
-
+	
 	// Read in tables from dialogue list resource
 	scriptS.seek(0);
-	for (i = 0; i < n_dialogue; i++) {
+	for (i = 0; i < stringsCount; i++) {
 		offset = scriptS.readUint16();
-		if (offset > dialogue_len) {
-			warning("Error, invalid string offset");
-			free(dialogue_list->str);
-			free(dialogue_list->str_off);
-			free(dialogue_list);
-			return NULL;
+		if (offset > stringsLength) {
+			error("invalid string offset");
 		}
-		dialogue_list->str[i] = (const char *)dialogue_p + offset;
-		dialogue_list->str_off[i] = offset;
+		strings->strings[i] = (const char *)stringsPointer + offset;
 	}
-
-	return dialogue_list;
 }
 
 // Reads a logical voice LUT from a voice LUT resource in memory.
@@ -452,7 +416,7 @@
 	}
 
 	n_voices = voicelut_len / 2;
-	if (n_voices != script->diag->n_dialogue) {
+	if (n_voices != script->strings->stringsCount) {
 		warning("Error: Voice LUT entries do not match dialogue entries");
 		return NULL;
 	}

Index: script.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/script.h,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- script.h	15 Dec 2004 00:24:11 -0000	1.29
+++ script.h	21 Dec 2004 06:49:07 -0000	1.30
@@ -75,7 +75,7 @@
 	kVarActor
 };
 
-enum {
+enum ThreadFlags {
 	kTFlagNone = 0,
 	kTFlagWaiting = 1,	// wait for even denoted in waitType
 	kTFlagFinished = 2,
@@ -83,20 +83,24 @@
 	kTFlagAsleep = 7	// Combination of all flags which can halt a thread
 };
 
-enum {
-	kTWaitNone = 0,		// waiting for nothing
-	kTWaitDelay,		// waiting for a timer
-	kTWaitSpeech,		// waiting for speech to finish
-	kTWaitDialogEnd,	// waiting for my dialog to finish
-	kTWaitDialogBegin,	// waiting for other dialog to finish
-	kTWaitWalk,			// waiting to finish walking
-	kTWaitRequest,		// a request is up
-	kTWaitPause
+enum ThreadWaitTypes {
+	kWaitTypeNone = 0,			// waiting for nothing
+	kWaitTypeDelay = 1,			// waiting for a timer
+	kWaitTypeSpeech = 2,		// waiting for speech to finish
+	kWaitTypeDialogEnd = 3,		// waiting for my dialog to finish
+	kWaitTypeDialogBegin = 4,	// waiting for other dialog to finish
+	kWaitTypeWalk = 5,			// waiting to finish walking
+	kWaitTypeRequest = 6,		// a request is up
+	kWaitTypePause = 7
+};
+
+enum OpCodes {
+	opSpeak = 0x53
 };
 
 struct SCRIPT_THREAD {
-	int flags;
-	int waitType;
+	int flags;				// ThreadFlags
+	int waitType;			// ThreadWaitTypes
 
 	uint sleepTime;
 	int ep_num; // Entrypoint number
@@ -135,6 +139,11 @@
 		assert(stackPtr < ARRAYSIZE(stackBuf));
 		return stackBuf[stackPtr++];
 	}
+	
+	void wait(int aWaitType) {
+		waitType = aWaitType;
+		flags |= kTFlagWaiting;
+	}
 
 	SCRIPT_THREAD() { memset(this, 0, sizeof(*this)); }
 };
@@ -154,10 +163,9 @@
 	PROC_TBLENTRY *entrypoints;
 };
 
-struct DIALOGUE_LIST {
-	unsigned int n_dialogue;
-	const char **str;
-	size_t *str_off;
+struct StringsList {
+	int stringsCount;
+	const char **strings;
 };
 
 struct VOICE_LUT {
@@ -168,7 +176,7 @@
 struct SCRIPTDATA {
 	int loaded;
 	SCRIPT_BYTECODE *bytecode;
-	DIALOGUE_LIST *diag;
+	StringsList *strings;
 	VOICE_LUT *voice;
 };
 
@@ -195,16 +203,16 @@
 	int loadScript(int scriptNum);
 	int freeScript();
 	SCRIPT_BYTECODE *loadBytecode(byte *bytecode_p, size_t bytecode_len);
-	DIALOGUE_LIST *loadDialogue(const byte *dialogue_p, size_t dialogue_len);
+	void loadStrings(const byte *stringsList, size_t stringsLength, StringsList *&strings);
 	VOICE_LUT *loadVoiceLUT(const byte *voicelut_p, size_t voicelut_len, SCRIPTDATA *script);
-	int disassemble(SCRIPT_BYTECODE *script_list, DIALOGUE_LIST *diag_list);
+	int disassemble(SCRIPT_BYTECODE *script_list, StringsList *strings);
 
 	bool isInitialized() const { return _initialized;  }
 	bool isVoiceLUTPresent() const { return _voiceLUTPresent; }
 	SCRIPTDATA *currentScript() { return _currentScript; }
 	void setBuffer(int idx, SCRIPT_DATABUF *ptr) { _dataBuf[idx] = ptr; }
 	SCRIPT_DATABUF *dataBuffer(int idx) { return _dataBuf[idx]; }
-//	YS_DL_LIST *threadList() { return _threadList; }
+	const char *getString(int index);
 
 	void scriptInfo();
 	void scriptExec(int argc, const char **argv);
@@ -220,10 +228,11 @@
 	SCRIPT_DATABUF *_dataBuf[SCRIPT_DATABUF_NUM];
 	ScriptThreadList _threadList;
 
+
+public:
 	bool _skipSpeeches;
 	bool _abortEnabled;
 
-public:
 	int _dbg_singlestep;
 	int _dbg_dostep;
 	SCRIPT_THREAD *_dbg_thread;
@@ -232,13 +241,15 @@
 public:
 	SCRIPT_THREAD *SThreadCreate();
 	int SThreadExecute(SCRIPT_THREAD *thread, int ep_num);
-	int SThreadExecThreads(uint msec);
+	int executeThreads(uint msec);
 	int SThreadHoldSem(SEMAPHORE *sem);
 	int SThreadReleaseSem(SEMAPHORE *sem);
 	int SThreadDebugStep();
 	void SThreadCompleteThread(void);
 	int SThreadDestroy(SCRIPT_THREAD *thread);
-	void SThreadAbortAll(void);
+
+	void wakeUpThreads(int waitType);
+	void wakeUpThreadsDelayed(int waitType, int sleepTime);
 
 private:
 	void setFramePtr(SCRIPT_THREAD *thread, int newPtr);

Index: sdebug.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/sdebug.cpp,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- sdebug.cpp	15 Dec 2004 00:24:11 -0000	1.20
+++ sdebug.cpp	21 Dec 2004 06:49:07 -0000	1.21
@@ -453,19 +453,19 @@
 	case 0x46:
 		SD_ADDTXT("LXOR |");
 		break;
-	case 0x53:
+	case opSpeak:
 		{
-			int n_voices;
-			int param1;
-			int param2;
+			int stringsCount;
+			uint16 actorId;
+			int speechFlags;
 
-			SD_ADDTXT("DLGP | ");
-			n_voices = readS.readByte();
-			param1 = readS.readUint16LE();
-			param2 = readS.readByte();
+			SD_ADDTXT("opSpeak | ");
+			stringsCount = readS.readByte();
+			actorId = readS.readUint16LE();
+			speechFlags = readS.readByte();
 			// ignored ?
 			readS.readUint16LE();
-			sprintf(tmp_buf, "%02X %04X %02X", n_voices, param1, param2);
+			sprintf(tmp_buf, "%02X %04X %02X", stringsCount, actorId, speechFlags);
 			SD_ADDTXT(tmp_buf);
 		}
 		break;

Index: sfuncs.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/sfuncs.cpp,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- sfuncs.cpp	17 Dec 2004 20:38:17 -0000	1.46
+++ sfuncs.cpp	21 Dec 2004 06:49:07 -0000	1.47
@@ -133,7 +133,7 @@
 int Script::SF_putString(SCRIPTFUNC_PARAMS) {
 	SDataWord_T param = thread->pop();
 
-	debug(1, currentScript()->diag->str[param]);
+	_vm->_console->DebugPrintf(getString(param));
 	return SUCCESS;
 }
 
@@ -146,9 +146,8 @@
 	if (!_skipSpeeches) {
 		time_param = thread->pop();
 		time = _vm->_sdata->readWordU(time_param);
-		time = time * 10;  // 72.8 ticks per second
-		thread->flags |= kTFlagWaiting;	// put thread to sleep
-		thread->waitType = kTWaitDelay;
+		thread->wait(kWaitTypeDelay); // put thread to sleep
+		thread->sleepTime = ticksToMSec(time);
 	}
 	return SUCCESS;
 }
@@ -191,7 +190,7 @@
 int Script::SF_setStatusText(SCRIPTFUNC_PARAMS) {
 	SDataWord_T param = thread->pop();
 
-	return _vm->_interface->setStatusText(currentScript()->diag->str[param]);
+	return _vm->_interface->setStatusText(getString(param));
 }
 
 // Script function #5 (0x05)

Index: sthread.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/sthread.cpp,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- sthread.cpp	17 Dec 2004 20:38:17 -0000	1.42
+++ sthread.cpp	21 Dec 2004 06:49:07 -0000	1.43
@@ -33,6 +33,8 @@
 #include "saga/sdata.h"
 #include "saga/game_mod.h"
 #include "saga/stream.h"
+#include "saga/scene.h"
+#include "saga/resnames.h"
 
 namespace Saga {
 
@@ -55,7 +57,7 @@
 	setFramePtr(new_thread, new_thread->stackPtr);
 
 	new_thread->flags = kTFlagWaiting;
-	new_thread->waitType = kTWaitPause;
+	new_thread->waitType = kWaitTypePause;
 
 	dataBuffer(4)->len = ARRAYSIZE(new_thread->threadVars);
 	dataBuffer(4)->data = new_thread->threadVars;
@@ -63,46 +65,67 @@
 	return new_thread;
 }
 
+void Script::wakeUpThreads(int waitType) {
+	SCRIPT_THREAD *thread;
+	ScriptThreadList::iterator threadIterator;
+	
+	for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
+		thread = threadIterator.operator->();
+		if ((thread->flags & kTFlagWaiting) && (thread->waitType == waitType)) {
+			thread->flags &= ~kTFlagWaiting;
+		}
+	}
+}
+
+void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) {
+	SCRIPT_THREAD *thread;
+	ScriptThreadList::iterator threadIterator;
 
-int Script::SThreadExecThreads(uint msec) {
+	for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) {
+		thread = threadIterator.operator->();
+		if ((thread->flags & kTFlagWaiting) && (thread->waitType == waitType)) {
+			thread->waitType = kWaitTypeDelay;
+			thread->sleepTime = sleepTime;
+		}
+	}
+}
+
+int Script::executeThreads(uint msec) {
 	SCRIPT_THREAD *thread;
+	ScriptThreadList::iterator threadIterator;
 
 	if (!isInitialized()) {
 		return FAILURE;
 	}
 
-	ScriptThreadList::iterator threadi = _threadList.begin();
+	threadIterator = _threadList.begin();
 
-	while (threadi != _threadList.end()) {
-		thread = (SCRIPT_THREAD *)threadi.operator->();
+	while (threadIterator != _threadList.end()) {
+		thread = threadIterator.operator->();
 
 		if (thread->flags & (kTFlagFinished | kTFlagAborted)) {
 			//if (thread->flags & kTFlagFinished) // FIXME. Missing function
 
 			
-			threadi = _threadList.erase(threadi);
+			threadIterator = _threadList.erase(threadIterator);
 			continue;
 		}
 
-		if (thread->flags & kTFlagWaiting) {
-			switch(thread->waitType) {
-			case kTWaitDelay:
-				if (thread->sleepTime < msec) {
-					thread->sleepTime = 0;
-				} else {
-					thread->sleepTime -= msec;
-				}
-
-				if (thread->sleepTime == 0)
-					thread->flags &= ~kTFlagWaiting;
-				break;
+		if ((thread->flags & kTFlagWaiting) && (thread->waitType == kWaitTypeDelay)) {
+			if (thread->sleepTime < msec) {
+				thread->sleepTime = 0;
+			} else {
+				thread->sleepTime -= msec;
 			}
+
+			if (thread->sleepTime == 0)
+				thread->flags &= ~kTFlagWaiting;			
 		}
 
 		if (!(thread->flags & kTFlagWaiting))
 			SThreadRun(thread, STHREAD_TIMESLICE);
 
-		++threadi;
+		++threadIterator;
 	}
 
 	return SUCCESS;
@@ -110,7 +133,7 @@
 
 void Script::SThreadCompleteThread(void) {
 	for (int i = 0; i < 40 &&  !_threadList.isEmpty() ; i++)
-		SThreadExecThreads(0);
+		executeThreads(0);
 }
 
 int Script::SThreadSetEntrypoint(SCRIPT_THREAD *thread, int ep_num) {
@@ -147,15 +170,7 @@
 	return SUCCESS;
 }
 
-void Script::SThreadAbortAll(void) {
-	// TODO: stop current speech
 
-	if (_abortEnabled) 
-		_skipSpeeches = true;
-
-	for (int i = 0; i < 10; i++)
-		_vm->_script->SThreadExecThreads(0);
-}
 
 unsigned char *Script::SThreadGetReadPtr(SCRIPT_THREAD *thread) {
 	return currentScript()->bytecode->bytecode_p + thread->i_offset;
@@ -215,7 +230,7 @@
 	int debug_print = 0;
 	int n_buf;
 	int bitstate;
-	int in_char;
+	int operandChar;
 	int i;
 	int unhandled = 0;
 
@@ -239,14 +254,17 @@
 	scriptS.seek(thread->i_offset);
 
 	for (instr_count = 0; instr_count < instr_limit; instr_count++) {
-		if (thread->sem.hold_count)
+		if (thread->flags & kTFlagWaiting)
+			break;
+
+		if (thread->sem.hold_count)  //TODO: remove it
 			break;                                                  
 
 		saved_offset = thread->i_offset;
-		in_char = scriptS.readByte();
+		operandChar = scriptS.readByte();
 
-		debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->i_offset, in_char, thread->stackSize());
-		switch (in_char) {
+		debug(2, "Executing thread offset: %lu (%x) stack: %d", thread->i_offset, operandChar, thread->stackSize());
+		switch (operandChar) {
 		case 0x01: // nextblock
 			// Some sort of "jump to the start of the next memory
 			// page" instruction, I think.
@@ -355,7 +373,6 @@
 				if (func_num >= SFUNC_NUM) {
 					_vm->_console->DebugPrintf(S_ERROR_PREFIX "Invalid script function number: (%X)\n", func_num);
 					thread->flags |= kTFlagAborted;
-					debug( 9, "Invalid script function number: (%X)\n", func_num);
 					break;
 				}
 
@@ -363,7 +380,6 @@
 				sfuncRetVal = (this->*sfunc)(thread, n_args);
 				if (sfuncRetVal != SUCCESS) {
 					_vm->_console->DebugPrintf(S_WARN_PREFIX "%X: Script function %d failed.\n", thread->i_offset, func_num);
-					debug( 9, "%X: Script function %d failed.\n", thread->i_offset, func_num);
 				}
 
 				if (func_num == 16) { // SF_gotoScene
@@ -371,7 +387,7 @@
 					break;
 				}
 
-				if (in_char == 0x18) // CALL function
+				if (operandChar == 0x18) // CALL function
 					thread->push(thread->retVal);
 
 				if (thread->flags & kTFlagAsleep)
@@ -393,11 +409,10 @@
 			if (thread->stackSize() == 0) {
 				_vm->_console->DebugPrintf("Script execution complete.\n");
 				thread->flags |= kTFlagFinished;
-				debug( 9, "Script execution complete.\n");
 			} else {
 				thread->i_offset = thread->pop();
 				/* int n_args = */ thread->pop();
-				if (in_char == 0x1B)
+				if (operandChar == 0x1B)
 					thread->push(scriptRetVal);
 			}
 			break;
@@ -493,7 +508,6 @@
 				}
 				if (!branch_found) {
 					_vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Random jump target out of bounds.\n", thread->i_offset);
-					debug(9, "%X: Random jump target out of bounds.\n", thread->i_offset);
 				}
 			}
 			break;
@@ -716,29 +730,55 @@
 
 // GAME INSTRUCTIONS  
 
-			// (DLGP): Play Character Dialogue
-		case 0x53:
+			// (opSpeak): Play Character Speech
+		case opSpeak:
 			{
-				int n_voices;
+				int stringsCount;
 				uint16 actorId;
-				int voice_rn;
+				int speechFlags;
+				int sampleResourceId = -1;
+				int first;
+				const char *strings[ACTOR_SPEECH_STRING_MAX];
 
-				n_voices = scriptS.readByte();
-				param1 = (SDataWord_T) scriptS.readUint16LE();
-				// ignored ?
-				scriptS.readByte();
-				scriptS.readUint16LE();
+				if (_vm->_actor->isSpeaking()) {
+					thread->wait(kWaitTypeSpeech);
+					return SUCCESS;
+				}
 
-				actorId = param1;
+				stringsCount = scriptS.readByte();
+				actorId =  scriptS.readUint16LE();
+				speechFlags = scriptS.readByte();
+				scriptS.readUint16LE(); // x,y skip
+				
+				if (stringsCount == 0)
+					error("opSpeak stringsCount == 0");
 
-				for (i = 0; i < n_voices; i++) {
-					data = thread->pop();
-					if (!isVoiceLUTPresent()) {
-						voice_rn = -1;
-					} else {
-						voice_rn = currentScript()->voice->voices[data];
+				if (stringsCount >= ACTOR_SPEECH_STRING_MAX)
+					error("opSpeak stringsCount=0x%X exceed ACTOR_SPEECH_STRING_MAX", stringsCount);
+				
+				data = first = thread->stackTop();
+				for (i = 0; i < stringsCount; i++) {
+					 data = thread->pop();
+					 strings[i] = getString(data);
+				}
+				// now data contains last string index
+
+				if (GAME_GetGame() == GAME_ITE_DISK) { // special ITE dos
+					if ((_vm->_scene->currentSceneNumber() == ITE_DEFAULT_SCENE) && (data >= 288) && (data <= (SCENE1_VOICE_138 - SCENE1_VOICE_009 + 288))) {
+						sampleResourceId = SCENE1_VOICE_009 + data - 288;
+					}
+				} else {
+					if (isVoiceLUTPresent()) {
+						if (currentScript()->voice->n_voices > first) {
+							sampleResourceId = currentScript()->voice->voices[first];
+						}
 					}
-					_vm->_actor->speak(actorId, currentScript()->diag->str[data], voice_rn, &thread->sem);
+				}
+
+				_vm->_actor->actorSpeech(actorId, strings, stringsCount, sampleResourceId, speechFlags);				
+
+				if (!(speechFlags & kSpeakAsync)) {
+					thread->wait(kWaitTypeSpeech);
 				}
 			}
 			break;
@@ -772,10 +812,8 @@
 // End instruction list
 
 		default:
-
-			_vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Invalid opcode encountered: (%X).\n", thread->i_offset, in_char);
+			_vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Invalid opcode encountered: (%X).\n", thread->i_offset, operandChar);
 			thread->flags |= kTFlagAborted;
-			debug(9, "%X: Invalid opcode encountered: (%X).\n", thread->i_offset, in_char);
 			break;
 		}
 
@@ -786,7 +824,6 @@
 			if (thread->i_offset >= scriptS.size()) {
 				_vm->_console->DebugPrintf("Out of range script execution at %x size %x\n", thread->i_offset, scriptS.size());
 				thread->flags |= kTFlagFinished;
-				debug(9, "Out of range script execution at %x size %x\n", thread->i_offset, scriptS.size());
 			}
 			else
 				scriptS.seek(thread->i_offset);
@@ -794,7 +831,6 @@
 		if (unhandled) {
 			_vm->_console->DebugPrintf(S_ERROR_PREFIX "%X: Unhandled opcode.\n", thread->i_offset);
 			thread->flags |= kTFlagAborted;
-			debug(9, "%X: Unhandled opcode.\n", thread->i_offset);
 		}
 		if ((thread->flags == kTFlagNone) && debug_print) {
 			SDebugPrintInstr(thread);

Index: xref.txt
===================================================================
RCS file: /cvsroot/scummvm/scummvm/saga/xref.txt,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- xref.txt	2 Nov 2004 08:37:14 -0000	1.15
+++ xref.txt	21 Dec 2004 06:49:07 -0000	1.16
@@ -68,7 +68,7 @@
 
 Interp.c
 ========
- dispatchThreads()         SThreadExecThreads()
+ dispatchThreads()         executeThreads()
  runThread()               SThreadCompleteThread()
  moduleList                _scriptLUT
  ModuleEntry->codeID       _scriptLUT->script_rn
@@ -90,7 +90,7 @@
 
 Actor.c
 =======
- abortAllSpeeches()        SThreadAbortAll()
+ abortAllSpeeches()        abortAllSpeeches()
 
 Main.c
 ======





More information about the Scummvm-git-logs mailing list