[Scummvm-cvs-logs] SF.net SVN: scummvm: [31581] scummvm/trunk/engines/kyra

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Sun Apr 20 00:22:00 CEST 2008


Revision: 31581
          http://scummvm.svn.sourceforge.net/scummvm/?rev=31581&view=rev
Author:   lordhoto
Date:     2008-04-19 15:22:00 -0700 (Sat, 19 Apr 2008)

Log Message:
-----------
Implemented some kyra opcodes and some chat handling code, now Malcolm should say something after crawling out of the dump.

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/animator_v3.cpp
    scummvm/trunk/engines/kyra/kyra_v3.cpp
    scummvm/trunk/engines/kyra/kyra_v3.h
    scummvm/trunk/engines/kyra/resource.cpp
    scummvm/trunk/engines/kyra/script_v3.cpp
    scummvm/trunk/engines/kyra/text.h
    scummvm/trunk/engines/kyra/text_v2.cpp
    scummvm/trunk/engines/kyra/text_v3.cpp
    scummvm/trunk/engines/kyra/text_v3.h

Modified: scummvm/trunk/engines/kyra/animator_v3.cpp
===================================================================
--- scummvm/trunk/engines/kyra/animator_v3.cpp	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/animator_v3.cpp	2008-04-19 22:22:00 UTC (rev 31581)
@@ -289,6 +289,12 @@
 	}
 }
 
+void KyraEngine_v3::flagAnimObjsForRefresh() {
+	debugC(9, kDebugLevelAnimator, "KyraEngine_v3::flagAnimObjsForRefresh()");
+	for (AnimObj *curEntry = _animList; curEntry; curEntry = curEntry->nextObject)
+		curEntry->needRefresh = true;
+}
+
 void KyraEngine_v3::updateCharacterAnim(int charId) {
 	debugC(9, kDebugLevelAnimator, "KyraEngine_v3::updateCharacterAnim(%d)", charId);
 
@@ -388,4 +394,30 @@
 	_sceneAnimMovie[anim]->close();
 }
 
+void KyraEngine_v3::setCharacterAnimDim(int w, int h) {
+	debugC(9, kDebugLevelAnimator, "KyraEngine_v3::setCharacterAnimDim(%d, %d)", w, h);
+	restorePage3();
+	_charBackUpWidth = _animObjects[0].width;
+	_charBackUpWidth2 = _animObjects[0].width2;
+	_charBackUpHeight = _animObjects[0].height;
+	_charBackUpHeight2 = _animObjects[0].height2;
+	
+	_animObjects[0].width2 = (w - _charBackUpWidth) / 2;
+	_animObjects[0].height2 = h - _charBackUpHeight;
+	_animObjects[0].width = w;
+	_animObjects[0].height = h;
+}
+
+void KyraEngine_v3::resetCharacterAnimDim() {
+	debugC(9, kDebugLevelAnimator, "KyraEngine_v3::resetCharacterAnimDim()");
+	restorePage3();
+	_animObjects[0].width2 = _charBackUpWidth2;
+	_animObjects[0].height2 = _charBackUpHeight2;
+	_animObjects[0].width = _charBackUpWidth;
+	_animObjects[0].height = _charBackUpHeight;
+	_charBackUpWidth2 = _charBackUpHeight2 = -1;
+	_charBackUpWidth = _charBackUpHeight = -1;
+}
+
 } // end of namespace Kyra
+

Modified: scummvm/trunk/engines/kyra/kyra_v3.cpp
===================================================================
--- scummvm/trunk/engines/kyra/kyra_v3.cpp	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/kyra_v3.cpp	2008-04-19 22:22:00 UTC (rev 31581)
@@ -61,7 +61,7 @@
 	_sceneList = 0;
 	memset(&_mainCharacter, 0, sizeof(_mainCharacter));
 	_mainCharacter.sceneId = 9;
-	_mainCharacter.unk4 = 0x4C;
+	_mainCharacter.height = 0x4C;
 	_mainCharacter.facing = 5;
 	_mainCharacter.animFrame = 0x57;
 	_mainCharacter.walkspeed = 5;
@@ -96,6 +96,16 @@
 	_lastProcessedSceneScript = 0;
 	_specialSceneScriptRunFlag = false;
 	_pathfinderFlag = 0;
+	_talkObjectList = 0;
+	_chatText = 0;
+	_chatObject = -1;
+	memset(&_chatScriptState, 0, sizeof(_chatScriptState));
+	memset(&_chatScriptData, 0, sizeof(_chatScriptData));
+	_voiceSoundChannel = -1;
+	_charBackUpWidth2 = _charBackUpHeight2 = -1;
+	_charBackUpWidth = _charBackUpHeight = -1;
+	_useActorBuffer = false;
+	_curStudioSFX = 283;
 }
 
 KyraEngine_v3::~KyraEngine_v3() {
@@ -138,6 +148,7 @@
 		delete _wsaSlots[i];
 
 	delete [] _sceneStrings;
+	delete [] _talkObjectList;
 }
 
 int KyraEngine_v3::init() {
@@ -401,6 +412,42 @@
 	}
 }
 
+void KyraEngine_v3::playVoice(int high, int low) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::playVoice(%d, %d)", high, low);
+	snd_playVoiceFile(high * 1000 + low);
+}
+
+void KyraEngine_v3::snd_playVoiceFile(int file) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::snd_playVoiceFile(%d)", file);
+	char filename[16];
+	snprintf(filename, 16, "%u.AUD", (uint)file);
+
+	Common::SeekableReadStream *stream = _res->getFileStream(filename);
+	if (stream)
+		_voiceSoundChannel = _soundDigital->playSound(stream, SoundDigital::kSoundTypeSpeech, 255);
+}
+
+bool KyraEngine_v3::snd_voiceIsPlaying() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::snd_voiceIsPlaying()");
+	return _soundDigital->isPlaying(_voiceSoundChannel);
+}
+
+void KyraEngine_v3::snd_stopVoice() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::snd_stopVoice()");
+	_soundDigital->stopSound(_voiceSoundChannel);
+}
+
+void KyraEngine_v3::playStudioSFX() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::playStudioSFX()");
+	if (_rnd.getRandomNumberRng(1, 2) != 2)
+		return;
+
+	playSoundEffect(_curStudioSFX++, 128);
+
+	if (_curStudioSFX > 291)
+		_curStudioSFX = 283;
+}
+
 #pragma mark -
 
 void KyraEngine_v3::preinit() {
@@ -491,7 +538,10 @@
 
 	_screen->_curPage = 0;
 
-	//XXX
+	_talkObjectList = new TalkObject[88];
+	memset(_talkObjectList, 0, sizeof(TalkObject)*88);
+	for (int i = 0; i < 88; ++i)
+		_talkObjectList[i].unk14 = -1;
 
 	musicUpdate(0);
 	updateMalcolmShapes();
@@ -941,6 +991,31 @@
 	_screen->updateScreen();
 }
 
+void KyraEngine_v3::updateWithText() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::update()");
+	updateInput();
+
+	musicUpdate(0);
+	updateMouse();
+	//XXX
+	updateSpecialSceneScripts();
+	updateCommandLine();
+	//XXX
+	musicUpdate(0);
+
+	restorePage3();
+	drawAnimObjects();
+	if (textEnabled() && _chatText) {
+		int curPage = _screen->_curPage;
+		_screen->_curPage = 2;
+		objectChatPrintText(_chatText, _chatObject);
+		_screen->_curPage = curPage;
+	}
+	refreshAnimObjects(0);
+
+	_screen->updateScreen();
+}
+
 void KyraEngine_v3::updateMouse() {
 	debugC(9, kDebugLevelMain, "KyraEngine_v3::updateMouse()");
 	int shape = 0, offsetX = 0, offsetY = 0;

Modified: scummvm/trunk/engines/kyra/kyra_v3.h
===================================================================
--- scummvm/trunk/engines/kyra/kyra_v3.h	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/kyra_v3.h	2008-04-19 22:22:00 UTC (rev 31581)
@@ -43,12 +43,14 @@
 struct Button;
 
 class KyraEngine_v3 : public KyraEngine {
+friend class TextDisplayer_v3;
 public:
 	KyraEngine_v3(OSystem *system, const GameFlags &flags);
 	~KyraEngine_v3();
 
 	Screen *screen() { return _screen; }
 	SoundDigital *soundDigital() { return _soundDigital; }
+	int language() const { return _lang; }
 
 	int go();
 
@@ -74,6 +76,7 @@
 	void handleInput(int x, int y);
 
 	void update();
+	void updateWithText();
 	void updateMouse();
 
 	void delay(uint32 millis, bool update = false, bool isMainLoop = false);
@@ -127,8 +130,16 @@
 	static const char *_sfxFileList[];
 	static const int _sfxFileListSize;
 
-	void snd_playVoiceFile(int) {}
+	int _voiceSoundChannel;
 
+	void playVoice(int high, int low);
+	void snd_playVoiceFile(int file);
+	bool snd_voiceIsPlaying();
+	void snd_stopVoice();
+
+	int _curStudioSFX;
+	void playStudioSFX();
+
 	// main menu
 	void initMainMenu();
 	void uninitMainMenu();
@@ -199,12 +210,20 @@
 	void refreshAnimObjects(int force);
 	void refreshAnimObjectsIfNeed();
 
+	void flagAnimObjsForRefresh();
+
 	bool _loadingState;
 	void updateCharacterAnim(int charId);
 
 	void updateSceneAnim(int anim, int newFrame);
 	void removeSceneAnimObject(int anim, int refresh);
 
+	int _charBackUpWidth2, _charBackUpHeight2;
+	int _charBackUpWidth, _charBackUpHeight;
+
+	void setCharacterAnimDim(int w, int h);
+	void resetCharacterAnimDim();
+
 	// interface
 	uint8 *_interface;
 	uint8 *_interfaceCommandLine;
@@ -373,7 +392,7 @@
 	struct Character {
 		uint16 sceneId;
 		uint16 dlgIndex;
-		uint8 unk4;
+		uint8 height;
 		uint8 facing;
 		uint16 animFrame;
 		//uint8 unk8, unk9;
@@ -407,12 +426,66 @@
 	int _lastCharPalLayer;
 	bool _charPalUpdate;
 
+
+	// talk object
+	struct TalkObject {
+		char filename[13];
+		int8 unkD;
+		int8 unkE;
+		int16 x, y;
+		uint8 color;
+		int8 unk14;
+	};
+
+	TalkObject *_talkObjectList;
+
+	// chat
+	int _vocHigh;
+
+	const char *_chatText;
+	int _chatObject;
+	uint32 _chatEndTime;
+	int _chatVocHigh, _chatVocLow;
+
+	ScriptData _chatScriptData;
+	ScriptState _chatScriptState;
+
+	int chatGetType(const char *text);
+	int chatCalcDuration(const char *text);
+
+	void objectChat(const char *text, int object, int vocHigh, int vocLow);
+	void objectChatInit(const char *text, int object, int vocHigh, int vocLow);
+	void objectChatPrintText(const char *text, int object);
+	void objectChatProcess(const char *script);
+	void objectChatWaitToFinish();
+
+	// special script code
+	bool _temporaryScriptExecBit;
+	bool _useFrameTable;
+	
+	Common::Array<const Opcode *> _opcodesTemporary;
+
+	int o3t_defineNewShapes(ScriptState *script);
+	int o3t_setCurrentFrame(ScriptState *script);
+	int o3t_playSoundEffect(ScriptState *script);
+	int o3t_getMalcolmShapes(ScriptState *script);
+
+	// special shape code
+	char _newShapeFilename[13];
+	int _newShapeLastEntry;
+	int _newShapeWidth, _newShapeHeight;
+	int _newShapeXAdd, _newShapeYAdd;
+
+	int _newShapeAnimFrame;
+	int _newShapeDelay;
+
 	// unk
 	uint8 *_unkBuffer1040Bytes;
 	uint8 *_costPalBuffer;
 	uint8 *_screenBuffer;
 	uint8 *_gfxBackUpRect;
 	uint8 *_paletteOverlay;
+	bool _useActorBuffer;
 
 	int _unk3, _unk4, _unk5;
 
@@ -422,8 +495,10 @@
 
 	// opcodes
 	int o3_setCharacterPos(ScriptState *script);
+	int o3_defineObject(ScriptState *script);
 	int o3_refreshCharacter(ScriptState *script);
 	int o3_showSceneFileMessage(ScriptState *script);
+	int o3_objectChat(ScriptState *script);
 	int o3_defineItem(ScriptState *script);
 	int o3_queryGameFlag(ScriptState *script);
 	int o3_resetGameFlag(ScriptState *script);
@@ -446,6 +521,8 @@
 	int o3_setHiddenItemsEntry(ScriptState *script);
 	int o3_getHiddenItemsEntry(ScriptState *script);
 	int o3_removeSceneAnimObject(ScriptState *script);
+	int o3_setVocHigh(ScriptState *script);
+	int o3_getVocHigh(ScriptState *script);
 	int o3_dummy(ScriptState *script);
 
 	// misc

Modified: scummvm/trunk/engines/kyra/resource.cpp
===================================================================
--- scummvm/trunk/engines/kyra/resource.cpp	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/resource.cpp	2008-04-19 22:22:00 UTC (rev 31581)
@@ -714,7 +714,7 @@
 		entry.offset = resOffset+4;
 
 		char realFilename[20];
-		snprintf(realFilename, 20, "%.08u.AUD", resFilename);
+		snprintf(realFilename, 20, "%u.AUD", resFilename);
 
 		uint32 curOffset = stream.pos();
 		stream.seek(entry.offset+2, SEEK_SET);

Modified: scummvm/trunk/engines/kyra/script_v3.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_v3.cpp	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/script_v3.cpp	2008-04-19 22:22:00 UTC (rev 31581)
@@ -48,6 +48,20 @@
 	return 0;
 }
 
+int KyraEngine_v3::o3_defineObject(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_defineObject(%p) (%d, '%s', %d, %d, %d, %d, %d, %d)", (const void *)script,
+			stackPos(0), stackPosString(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5), stackPos(6), stackPos(7));
+	TalkObject &obj = _talkObjectList[stackPos(0)];
+	strcpy(obj.filename, stackPosString(1));
+	obj.unkD = stackPos(2);
+	obj.unkE = stackPos(3);
+	obj.x = stackPos(4);
+	obj.y = stackPos(5);
+	obj.color = stackPos(6);
+	obj.unk14 = stackPos(7);
+	return 0;
+}
+
 int KyraEngine_v3::o3_refreshCharacter(ScriptState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_refreshCharacter(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
 	const int frame = stackPos(0);
@@ -75,6 +89,17 @@
 	return 0;
 }
 
+int KyraEngine_v3::o3_objectChat(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_objectChat(%p) (%d)", (const void *)script, stackPos(0));
+	int id = stackPos(0);
+	const char *str = (const char*)getTableEntry(_useActorBuffer ? _actorFile : _sceneStrings, id);
+	if (str) {
+		objectChat(str, 0, _vocHigh, id);
+		playStudioSFX();
+	}
+	return 0;
+}
+
 int KyraEngine_v3::o3_defineItem(ScriptState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_defineItem(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
 	int freeItem = findFreeItem();
@@ -312,11 +337,62 @@
 	return 0;
 }
 
+int KyraEngine_v3::o3_setVocHigh(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_setVocHigh(%p) (%d)", (const void *)script, stackPos(0));
+	_vocHigh = stackPos(0);
+	return 0;
+}
+
+int KyraEngine_v3::o3_getVocHigh(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_getVocHigh(%p) ()", (const void *)script);
+	return _vocHigh;
+}
+
 int KyraEngine_v3::o3_dummy(ScriptState *script) {
 	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3_dummy(%p) ()", (const void *)script);
 	return 0;
 }
 
+#pragma mark -
+
+int KyraEngine_v3::o3t_defineNewShapes(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3t_defineNewShapes(%p) ('%s', %d, %d, %d, %d, %d)", (const void *)script,
+			stackPosString(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
+	strcpy(_newShapeFilename, stackPosString(0));
+	_newShapeLastEntry = stackPos(1);
+	_newShapeWidth = stackPos(2);
+	_newShapeHeight = stackPos(3);
+	_newShapeXAdd = stackPos(4);
+	_newShapeYAdd = stackPos(5);
+	return 0;
+}
+
+int KyraEngine_v3::o3t_setCurrentFrame(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3t_setCurrentFrame(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
+	static const uint8 frameTable[] = {
+		0x58, 0xD8, 0xD8, 0x98, 0x78, 0x78, 0xB8, 0xB8
+	};
+
+	_newShapeAnimFrame = stackPos(0);
+	if (_useFrameTable)
+		_newShapeAnimFrame += frameTable[_mainCharacter.facing];
+
+	_newShapeDelay = stackPos(1);
+	_temporaryScriptExecBit = true;
+	return 0;
+}
+
+int KyraEngine_v3::o3t_playSoundEffect(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3t_playSoundEffect(%p) (%d)", (const void *)script, stackPos(0));
+	playSoundEffect(stackPos(0), 200);	
+	return 0;
+}
+
+int KyraEngine_v3::o3t_getMalcolmShapes(ScriptState *script) {
+	debugC(3, kDebugLevelScriptFuncs, "KyraEngine_v3::o3t_getMalcolmShapes(%p) ()", (const void *)script);
+	return _malcolmShapes;
+}
+
 typedef Functor1Mem<ScriptState*, int, KyraEngine_v3> OpcodeV3;
 #define Opcode(x) OpcodeV3(this, &KyraEngine_v3::x)
 #define OpcodeUnImpl() OpcodeV3(this, 0)
@@ -325,7 +401,7 @@
 		// 0x00
 		OpcodeUnImpl(),
 		Opcode(o3_setCharacterPos),
-		OpcodeUnImpl(),
+		Opcode(o3_defineObject),
 		Opcode(o3_refreshCharacter),
 		// 0x04
 		OpcodeUnImpl(),
@@ -361,7 +437,7 @@
 		OpcodeUnImpl(),
 		OpcodeUnImpl(),
 		OpcodeUnImpl(),
-		OpcodeUnImpl(),
+		Opcode(o3_objectChat),
 		// 0x20
 		OpcodeUnImpl(),
 		Opcode(o3_dummy),
@@ -531,12 +607,12 @@
 		OpcodeUnImpl(),
 		OpcodeUnImpl(),
 		OpcodeUnImpl(),
-		OpcodeUnImpl(),
+		Opcode(o3_setVocHigh),
 		// 0xa8
+		Opcode(o3_getVocHigh),
 		OpcodeUnImpl(),
 		OpcodeUnImpl(),
 		OpcodeUnImpl(),
-		OpcodeUnImpl(),
 		// 0xac
 		OpcodeUnImpl(),
 		Opcode(o3_dummy),
@@ -546,6 +622,20 @@
 
 	for (int i = 0; i < ARRAYSIZE(opcodeTable); ++i)
 		_opcodes.push_back(&opcodeTable[i]);
+	
+	static const OpcodeV3 tempOpcodeTable[] = {
+		Opcode(o3t_defineNewShapes),
+		Opcode(o3t_setCurrentFrame),
+		Opcode(o3t_playSoundEffect),
+		Opcode(o3_dummy),
+		// 0x0a
+		OpcodeUnImpl(),
+		Opcode(o3_getRand),
+		Opcode(o3_dummy)
+	};
+	
+	for (int i = 0; i < ARRAYSIZE(tempOpcodeTable); ++i)
+		_opcodesTemporary.push_back(&tempOpcodeTable[i]);
 }
 
 } // end of namespace Kyra

Modified: scummvm/trunk/engines/kyra/text.h
===================================================================
--- scummvm/trunk/engines/kyra/text.h	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/text.h	2008-04-19 22:22:00 UTC (rev 31581)
@@ -68,7 +68,7 @@
 
 	enum {
 		TALK_SUBSTRING_LEN = 80,
-		TALK_SUBSTRING_NUM = 5
+		TALK_SUBSTRING_NUM = 6
 	};
 
 	char _talkBuffer[1040];

Modified: scummvm/trunk/engines/kyra/text_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/text_v2.cpp	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/text_v2.cpp	2008-04-19 22:22:00 UTC (rev 31581)
@@ -48,7 +48,7 @@
 	_vm->restorePage3();
 	_vm->drawAnimObjects();
 	_screen->hideMouse();
-	_screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, 2, 0);
+	_screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, 2, 0, Screen::CR_NO_P_CHECK);
 	_screen->showMouse();
 	_vm->flagAnimObjsForRefresh();
 	_vm->refreshAnimObjects(0);

Modified: scummvm/trunk/engines/kyra/text_v3.cpp
===================================================================
--- scummvm/trunk/engines/kyra/text_v3.cpp	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/text_v3.cpp	2008-04-19 22:22:00 UTC (rev 31581)
@@ -33,6 +33,101 @@
 	: TextDisplayer(vm, screen), _vm(vm), _screen(screen) {
 }
 
+char *TextDisplayer_v3::preprocessString(const char *str) {
+	debugC(9, kDebugLevelMain, "TextDisplayer_v3::preprocessString('%s')", str);
+	strcpy(_talkBuffer, str);
+
+	char *p = _talkBuffer;
+	while (*p) {
+		if (*p++ == '\r')
+			return _talkBuffer;
+	}
+
+	p = _talkBuffer;
+	Screen::FontId curFont = _screen->setFont(Screen::FID_8_FNT);
+	_screen->_charWidth = -2;
+
+	const int maxTextWidth = (_vm->language() == 0) ? 176 : 240;
+	int textWidth = _screen->getTextWidth(p);
+
+	if (textWidth > maxTextWidth) {
+		int count = 0, offs = 0;
+		if (textWidth > (3*maxTextWidth)) {
+			count = getCharLength(p, textWidth/4);
+			offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count);
+			p += count + offs;
+		}
+
+		if (textWidth > (2*maxTextWidth)) {
+			count = getCharLength(p, textWidth/3);
+			offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count);
+			p += count + offs;
+			textWidth = _screen->getTextWidth(p);
+		}
+
+		count = getCharLength(p, textWidth/2);
+		offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count);	
+		p += count + offs;
+		textWidth = _screen->getTextWidth(p);
+
+		if (textWidth > maxTextWidth) {
+			count = getCharLength(p, textWidth/2);
+			offs = dropCRIntoString(p, getCharLength(p, maxTextWidth), count);	
+		}
+	}
+
+	_screen->setFont(curFont);
+	return _talkBuffer;
+}
+
+int TextDisplayer_v3::dropCRIntoString(char *str, int minOffs, int maxOffs) {
+	debugC(9, kDebugLevelMain, "TextDisplayer_v3::dropCRIntoString('%s', %d, %d)", str, maxOffs, minOffs);
+
+	int offset = 0;
+	char *proc = str + minOffs;
+
+	for (int i = minOffs; i < maxOffs; ++i) {
+		if (*proc == ' ') {
+			*proc = '\r';
+			return offset;
+		} else if (*proc == '-') {
+			memmove(proc+1, proc, strlen(proc)+1);
+			*(++proc) = '\r';
+			++offset;
+			return offset;
+		}
+
+		++offset;
+		++proc;
+
+		if (!*proc)
+			return 0;
+	}
+
+	offset = 0;
+	proc = str + minOffs;
+	for (int i = minOffs; i >= 0; --i) {
+		if (*proc == ' ') {
+			*proc = '\r';
+			return offset;
+		} else if (*proc == '-') {
+			memmove(proc+1, proc, strlen(proc)+1);
+			*(++proc) = '\r';
+			++offset;
+			return offset;
+		}
+
+		--offset;
+		--proc;
+
+		if (!*proc)
+			return 0;
+	}
+
+	*(str + minOffs) = '\r';
+	return 0;
+}
+
 void TextDisplayer_v3::printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font) {
 	debugC(9, kDebugLevelMain, "TextDisplayer_v3::printText('%s', %d, %d, %d, %d, %d)", str, x, y, c0, c1, c2);
 	uint8 colorMap[] = { 0, 255, 240, 240 };
@@ -45,4 +140,242 @@
 	_screen->setFont(curFont);
 }
 
+void TextDisplayer_v3::restoreScreen() {
+	debugC(9, kDebugLevelMain, "TextDisplayer_v3::restoreScreen()");
+	_vm->restorePage3();
+	_vm->drawAnimObjects();
+	_screen->hideMouse();
+	_screen->copyRegion(_talkCoords.x, _talkMessageY, _talkCoords.x, _talkMessageY, _talkCoords.w, _talkMessageH, 2, 0, Screen::CR_NO_P_CHECK);
+	_screen->showMouse();
+	_vm->flagAnimObjsForRefresh();
+	_vm->refreshAnimObjects(0);
+}
+
+void TextDisplayer_v3::calcWidestLineBounds(int &x1, int &x2, int w, int x) {
+	debugC(9, kDebugLevelMain, "TextDisplayer_v3::calcWidestLineBounds(%d, %d)", w, x);
+	x1 = x;
+	x1 -= (w >> 1);
+	x2 = x1 + w + 1;
+
+	if (x1 + w >= 311)
+		x1 = 311 - w - 1;
+
+	if (x1 < 8)
+		x1 = 8;
+
+	x2 = x1 + w + 1;
+}
+
+#pragma mark -
+
+int KyraEngine_v3::chatGetType(const char *str) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::chatGetType('%s')", str);
+	while (*str)
+		++str;
+	--str;
+	switch (*str) {
+	case '!':
+		return 2;
+
+	case ')':
+		return 3;
+
+	case '?':
+		return 1;
+
+	case '.':
+	default:
+		return 0;
+	}
+}
+
+int KyraEngine_v3::chatCalcDuration(const char *str) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::chatCalcDuration('%s')", str);
+	return MAX<int>(120, strlen(str)*6);
+}
+
+void KyraEngine_v3::objectChat(const char *str, int object, int vocHigh, int vocLow) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::objectChat('%s', %d, %d, %d)", str, object, vocHigh, vocLow);
+
+	if (_mainCharacter.animFrame == 87 || _mainCharacter.animFrame == 0xFFFF || _mainCharacter.x1 <= 0 || _mainCharacter.y1 <= 0)
+		return;
+
+	_chatVocLow = _chatVocHigh = -1;
+	objectChatInit(str, object, vocHigh, vocLow);
+	_chatText = str;
+	_chatObject = object;
+	int chatType = chatGetType(str);
+
+	if (_mainCharacter.facing > 7)
+		_mainCharacter.facing = 5;
+
+	static const uint8 talkScriptTable[] = {
+		0x10, 0x11, 0x12, 0x13,
+		0x0C, 0x0D, 0x0E, 0x0F,
+		0x0C, 0x0D, 0x0E, 0x0F,
+		0x04, 0x05, 0x06, 0x07,
+		0x00, 0x01, 0x02, 0x03,
+		0x00, 0x01, 0x02, 0x03,
+		0x08, 0x09, 0x0A, 0x0B,
+		0x08, 0x09, 0x0A, 0x0B
+	};
+
+	static const char *talkFilenameTable[] = {
+		"MTFL00S.EMC", "MTFL00Q.EMC", "MTFL00E.EMC", "MTFL00T.EMC",
+		"MTFR00S.EMC", "MTFR00Q.EMC", "MTFR00E.EMC", "MTRF00T.EMC",
+		 "MTL00S.EMC",  "MTL00Q.EMC",  "MTL00E.EMC",  "MTL00T.EMC",
+		 "MTR00S.EMC",  "MTR00Q.EMC",  "MTR00E.EMC",  "MTR00T.EMC",
+		 "MTA00S.EMC",  "MTA00Q.EMC",  "MTA00Q.EMC",  "MTA00T.EMC"
+	};
+
+	int chat = talkScriptTable[chatType + _mainCharacter.facing * 4];
+	objectChatProcess(talkFilenameTable[chat]);
+	_text->restoreScreen();
+	_mainCharacter.animFrame = _characterFrameTable[_mainCharacter.facing];
+	updateCharacterAnim(0);
+	_chatText = 0;
+	_chatObject = -1;
+	//setNextIdleAnimTimer();
+}
+
+void KyraEngine_v3::objectChatInit(const char *str, int object, int vocHigh, int vocLow) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::objectChatInit('%s', %d, %d, %d)", str, object, vocHigh, vocLow);
+	str = _text->preprocessString(str);
+	int lineNum = _text->buildMessageSubstrings(str);
+	
+	int xPos = 0, yPos = 0;
+
+	if (!object) {
+		int scale = getScale(_mainCharacter.x1, _mainCharacter.y1);
+		yPos = _mainCharacter.y1 - ((_mainCharacter.height * scale) >> 8) - 8;
+		xPos = _mainCharacter.x1;
+	} else {
+		yPos = _talkObjectList[object].y;
+		xPos = _talkObjectList[object].x;
+	}
+
+	yPos -= lineNum * 10;
+	yPos = MAX(yPos, 0);
+	_text->_talkMessageY = yPos;
+	_text->_talkMessageH = lineNum*10;
+
+	int width = _text->getWidestLineWidth(lineNum);
+	_text->calcWidestLineBounds(xPos, yPos, width, xPos);
+	_text->_talkCoords.x = xPos;
+	_text->_talkCoords.w = width + 2;
+
+	restorePage3();
+
+	_screen->hideMouse();
+
+	if (textEnabled()) {
+		objectChatPrintText(str, object);
+		_chatEndTime = _system->getMillis() + chatCalcDuration(str) * _tickLength;
+	} else {
+		_chatEndTime = _system->getMillis();
+	}
+
+	if (speechEnabled()) {
+		_chatVocHigh = vocHigh;
+		_chatVocLow = vocLow;
+	} else {
+		_chatVocHigh = _chatVocLow = -1;
+	}
+
+	_screen->showMouse();
+}
+
+void KyraEngine_v3::objectChatPrintText(const char *str, int object) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::objectChatPrintText('%s', %d)", str, object);
+	int c1 = _talkObjectList[object].color;
+	str = _text->preprocessString(str);
+	int lineNum = _text->buildMessageSubstrings(str);
+	int maxWidth = _text->getWidestLineWidth(lineNum);
+	int x = (object == 0) ? _mainCharacter.x1 : _talkObjectList[object].x;
+	int cX1 = 0, cX2 = 0;
+	_text->calcWidestLineBounds(cX1, cX2, maxWidth, x);
+
+	for (int i = 0; i < lineNum; ++i) {
+		str = &_text->_talkSubstrings[i*_text->maxSubstringLen()];
+
+		int y = _text->_talkMessageY + i * 10;
+		x = _text->getCenterStringX(str, cX1, cX2);
+
+		_text->printText(str, x, y, c1, 0xF0, 0);
+	}
+}
+
+void KyraEngine_v3::objectChatProcess(const char *script) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::objectChatProcess('%s')", script);
+
+	memset(&_chatScriptData, 0, sizeof(_chatScriptData));
+	memset(&_chatScriptState, 0, sizeof(_chatScriptState));
+
+	_scriptInterpreter->loadScript(script, &_chatScriptData, &_opcodesTemporary);
+	_scriptInterpreter->initScript(&_chatScriptState, &_chatScriptData);
+	_scriptInterpreter->startScript(&_chatScriptState, 0);
+	while (_scriptInterpreter->validScript(&_chatScriptState))
+		_scriptInterpreter->runScript(&_chatScriptState);
+
+	if (_chatVocHigh >= 0) {
+		playVoice(_chatVocHigh, _chatVocLow);
+		_chatVocHigh = _chatVocLow = -1;
+	}
+
+	_useFrameTable = true;
+	objectChatWaitToFinish();
+	_useFrameTable = false;
+
+	_scriptInterpreter->unloadScript(&_chatScriptData);
+}
+
+void KyraEngine_v3::objectChatWaitToFinish() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v3::objectChatWaitToFinish()");
+	int charAnimFrame = _mainCharacter.animFrame;
+	setCharacterAnimDim(_newShapeWidth, _newShapeHeight);
+
+	_scriptInterpreter->initScript(&_chatScriptState, &_chatScriptData);
+	_scriptInterpreter->startScript(&_chatScriptState, 1);
+
+	bool running = true;
+	const uint32 endTime = _chatEndTime;
+	resetSkipFlag();
+
+	while (running && !_quitFlag) {
+		if (!_scriptInterpreter->validScript(&_chatScriptState))
+			_scriptInterpreter->startScript(&_chatScriptState, 1);
+
+		_temporaryScriptExecBit = false;
+		while (!_temporaryScriptExecBit && _scriptInterpreter->validScript(&_chatScriptState)) {
+			musicUpdate(0);
+			_scriptInterpreter->runScript(&_chatScriptState);
+		}
+
+		int curFrame = _newShapeAnimFrame;
+		uint32 delayTime = _newShapeDelay;
+
+		_mainCharacter.animFrame = curFrame;
+		updateCharacterAnim(0);
+
+		uint32 nextFrame = _system->getMillis() + delayTime * _tickLength;
+
+		while (_system->getMillis() < nextFrame && !_quitFlag) {
+			updateWithText();
+
+			const uint32 curTime = _system->getMillis();
+			if ((textEnabled() && !speechEnabled() && curTime > endTime) || (speechEnabled() && !snd_voiceIsPlaying()) || skipFlag()) {
+				resetSkipFlag();
+				nextFrame = curTime;
+				running = false;
+			}
+
+			delay(10);
+		}
+	}
+
+	_mainCharacter.animFrame = charAnimFrame;
+	updateCharacterAnim(0);
+	resetCharacterAnimDim();
+}
+
 } // end of namespace Kyra

Modified: scummvm/trunk/engines/kyra/text_v3.h
===================================================================
--- scummvm/trunk/engines/kyra/text_v3.h	2008-04-19 17:17:48 UTC (rev 31580)
+++ scummvm/trunk/engines/kyra/text_v3.h	2008-04-19 22:22:00 UTC (rev 31581)
@@ -33,10 +33,18 @@
 namespace Kyra {
 
 class TextDisplayer_v3 : public TextDisplayer {
+friend class KyraEngine_v3;
 public:
 	TextDisplayer_v3(KyraEngine_v3 *vm, Screen_v3 *screen);
 
+	char *preprocessString(const char *str);
+	int dropCRIntoString(char *str, int minOffs, int maxOffs);
+
 	void printText(const char *str, int x, int y, uint8 c0, uint8 c1, uint8 c2, Screen::FontId font=Screen::FID_8_FNT);
+
+	void restoreScreen();
+
+	void calcWidestLineBounds(int &x1, int &x2, int w, int x);
 protected:
 	KyraEngine_v3 *_vm;
 	Screen_v3 *_screen;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list