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

vinterstum at users.sourceforge.net vinterstum at users.sourceforge.net
Sat Oct 20 00:16:00 CEST 2007


Revision: 29233
          http://scummvm.svn.sourceforge.net/scummvm/?rev=29233&view=rev
Author:   vinterstum
Date:     2007-10-19 15:16:00 -0700 (Fri, 19 Oct 2007)

Log Message:
-----------
Committing [ 1816080 ] KYRA: Intro Patch for HoF, from Florian, with some cleanup and a minor fix

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/gui_v2.cpp
    scummvm/trunk/engines/kyra/kyra_v2.cpp
    scummvm/trunk/engines/kyra/kyra_v2.h
    scummvm/trunk/engines/kyra/screen.cpp
    scummvm/trunk/engines/kyra/screen_v2.cpp
    scummvm/trunk/engines/kyra/screen_v2.h
    scummvm/trunk/engines/kyra/sequences_v2.cpp
    scummvm/trunk/engines/kyra/staticres.cpp
    scummvm/trunk/engines/kyra/wsamovie.cpp
    scummvm/trunk/engines/kyra/wsamovie.h

Modified: scummvm/trunk/engines/kyra/gui_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/gui_v2.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/gui_v2.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -63,10 +63,12 @@
 	int charWidthBackUp = _screen->_charWidth;
 	
 	_screen->_charWidth = -2;
+
 	if (_flags.gameID == GI_KYRA2)
 		_screen->setScreenDim(11);
 	else
 		_screen->setScreenDim(3);
+
 	int backUpX = _screen->_curDim->sx;
 	int backUpY = _screen->_curDim->sy;
 	int backUpWidth = _screen->_curDim->w;
@@ -101,14 +103,21 @@
 			int item = (mouse.y - menuRect.top) / fh;
 
 			if (item != selected) {
-				gui_printString(strings[selected], textPos, menuRect.top + selected * fh, 0x80, 0, 5);
-				gui_printString(strings[item], textPos, menuRect.top + item * fh, 0xFF, 0, 5);
+				gui_printString(strings[selected], textPos, menuRect.top + selected * fh, (_flags.gameID == GI_KYRA3) ? 0x80 : 0xd7, 0, 5);
+				gui_printString(strings[item], textPos, menuRect.top + item * fh, (_flags.gameID == GI_KYRA3) ? 0xFF : 0xd6, 0, 5);
 
 				selected = item;
 			}
 
 			if (mousePressed) {
-				// TODO: Flash the text
+				for (int i = 0; i < 3; i++) {
+					gui_printString(strings[selected], textPos, menuRect.top + selected * fh, (_flags.gameID == GI_KYRA3) ? 0x80 : 0xd7, 0, 5);
+					_screen->updateScreen();
+					_system->delayMillis(50);
+					gui_printString(strings[selected], textPos, menuRect.top + selected * fh, (_flags.gameID == GI_KYRA3) ? 0xFF : 0xd6, 0, 5);
+					_screen->updateScreen();
+					_system->delayMillis(50);
+				}
 				command = item;
 				break;
 			}
@@ -126,10 +135,17 @@
 	return command;
 }
 
-void KyraEngine_v2::gui_drawMainMenu(const char * const *strings, int select) {
+void KyraEngine_v2::gui_drawMainMenu(const char *const *strings, int select) {
 	debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_drawMainMenu(%p)", (const void*)strings);
-	static const uint16 menuTable[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 };
-	
+	static const uint16 menuTable2[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0xd7, 0xd6, 0x00, 0x01, 0x02, 0x03 };
+	static const uint16 menuTable3[] = { 0x01, 0x04, 0x0C, 0x04, 0x00, 0x80, 0xFF, 0x00, 0x01, 0x02, 0x03 };
+	const uint16 *menuTable;
+
+	if (_flags.gameID == GI_KYRA3)
+		menuTable = menuTable3;
+	else
+		menuTable = menuTable2;
+
 	int top = _screen->_curDim->sy;
 	top += menuTable[1];
 	
@@ -143,8 +159,8 @@
 void KyraEngine_v2::gui_drawMainBox(int x, int y, int w, int h, int fill) {
 	debugC(9, kDebugLevelMain, "KyraEngine_v2::gui_drawMainBox(%d, %d, %d, %d, %d)", x, y, w, h, fill);
 	static const uint8 kyra3ColorTable[] = { 0x16, 0x19, 0x1A, 0x16 };
-	static const uint8 kyra2ColorTable[] = { 0x0, 0x19, 0x28, 0xc8 };
-	
+	static const uint8 kyra2ColorTable[] = {0xd8, 0xda, 0xd9, 0xd8 };
+
 	const uint8 *colorTable;
 	if (_flags.gameID == GI_KYRA3)
 		colorTable = kyra3ColorTable;
@@ -196,3 +212,4 @@
 }
 
 } // end of namespace Kyra
+

Modified: scummvm/trunk/engines/kyra/kyra_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/kyra_v2.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/kyra_v2.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -44,6 +44,12 @@
 	_debugger = 0;
 	_screen = 0;
 	_text = 0;
+
+	_pageBuffer1 = _pageBuffer2 = 0;
+	_seqProcessedString = 0;
+	_activeWSA = 0;
+	_activeText = 0;
+	_seqWsa = 0;
 	
 	_gamePlayBuffer = 0;
 	_cCodeBuffer = _optionsBuffer = _chapterBuffer = 0;
@@ -83,6 +89,8 @@
 }
 
 KyraEngine_v2::~KyraEngine_v2() {
+	seq_uninit();
+
 	delete [] _mouseSHPBuf;
 	delete _screen;
 	delete _text;
@@ -116,10 +124,14 @@
 	_screen->setAnimBlockPtr(3504);
 	_screen->setScreenDim(0);
 	
-	assert(_introStringsSize == 21);
-	for (int i = 0; i < 21; i++)
-		_introStringsDuration[i] = strlen(_introStrings[i]) * 8;
+	for (int i = 0; i < 33; i++)
+		_sequenceStringsDuration[i] = strlen(_sequenceStrings[i]) * 8;
 	
+	_abortIntroFlag = false;
+
+	_sequenceSoundList = (const char * const *) _sequenceSoundListPC;
+	_sequenceSoundListSize = _sequenceSoundListPCSize;
+
 	// No mouse display in demo
 	if (_flags.isDemo)
 		return 0;
@@ -136,7 +148,11 @@
 	return 0;
 }
 
-int KyraEngine_v2::go() {	
+int KyraEngine_v2::go() {
+	// TODO move this to a better location, since for ingame we setup
+	// our soundfile list in KyraEngine_v2::startup for example
+	// so this should be just used in the sequenceplayer code,
+	// so maybe move this to KyraEngine_v2::seq_init
 	if (_flags.isDemo) {
 		static const char *soundFileList[] = {
 			"K2_DEMO",
@@ -157,47 +173,19 @@
 	_res->unloadPakFile("OUTFARM.PAK");
 	_res->unloadPakFile("FLYTRAP.PAK");
 
-	//seq_playSequences(kSequenceVirgin, kSequenceWestwood);
-	mainMenu();
+	seq_playSequences(kSequenceVirgin, kSequenceZanfaun);
 
+	if (_menuChoice == 1) {
+		startup();
+		runLoop();
+		cleanup();
+	} else if (_menuChoice == 3) {
+		// Load Savegame
+	}
+
 	return 0;
 }
 
-void KyraEngine_v2::mainMenu() {
-	bool running = true;
-
-	while (running && !_quitFlag) {
-		seq_playSequences(kSequenceTitle);
-		_screen->showMouse();
-		
-		switch (gui_handleMainMenu()) {
-			case 0:
-				_screen->showMouse();
-
-				// load just the pak files needed for ingame
-				_res->unloadAllPakFiles();
-				_res->loadFileList("FILEDATA.FDT");
-
-				startup();
-				runLoop();
-				cleanup();
-				running = false;
-				break;
-			case 1:
-				seq_playSequences(kSequenceOverview, kSequenceZanFaun); 
-				break;
-			case 2:
-				break;
-			case 3:
-				running = false;
-				break;
-			default:
-				break;
-		}
-		_screen->hideMouse();
-	}
-}
-
 void KyraEngine_v2::startup() {
 	_sound->setSoundFileList(_dosSoundFileList, _dosSoundFileListSize);
 	_trackMap = _dosTrackMap;
@@ -1708,3 +1696,4 @@
 
 } // end of namespace Kyra
 
+

Modified: scummvm/trunk/engines/kyra/kyra_v2.h
===================================================================
--- scummvm/trunk/engines/kyra/kyra_v2.h	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/kyra_v2.h	2007-10-19 22:16:00 UTC (rev 29233)
@@ -36,15 +36,44 @@
 
 enum kSequences {
 	kSequenceVirgin = 0,
-	kSequenceWestwood = 1,
-	kSequenceTitle = 2,
-	kSequenceOverview = 3,
-	kSequenceLibrary = 4,
-	kSequenceHand = 5,
-	kSequencePoint = 6,
-	kSequenceZanFaun = 7
+	kSequenceWestwood,
+	kSequenceTitle,
+	kSequenceOverview,
+	kSequenceLibrary,
+	kSequenceHand,
+	kSequencePoint,
+	kSequenceZanfaun,
+
+	kSequenceFunters,
+	kSequenceFerb,
+	kSequenceFish,
+	kSequenceFheep,
+	kSequenceFarmer,
+	kSequenceFuards,
+	kSequenceFirates,
+	kSequenceFrash,
+
+	kSequenceArraySize
 };
 
+enum kNestedSequences {
+	kSequenceFiggle = 0,
+	kSequenceOver1,
+	kSequenceOver2,
+	kSequenceForest,
+	kSequenceDragon,
+	kSequenceDarm,
+	kSequenceLibrary2,
+	kSequenceLibrary3,
+	kSequenceMarco,
+	kSequenceHand1a,
+	kSequenceHand1b,
+	kSequenceHand1c,
+	kSequenceHand2,
+	kSequenceHand3,
+	kSequenceHand4
+};
+
 class WSAMovieV2;
 class KyraEngine_v2;
 class TextDisplayer_v2;
@@ -56,36 +85,64 @@
 };
 
 struct ActiveWSA {
+	int16 flags;
 	WSAMovieV2 *movie;
-	uint16 currentFrame;
+	uint16 startFrame;
 	uint16 endFrame;
 	uint16 frameDelay;
+	int (KyraEngine_v2::*callback)(WSAMovieV2*, int, int, int);
 	uint32 nextFrame;
-	void (KyraEngine_v2::*callback)(int);
+	uint16 currentFrame;
+	uint16 lastFrame;
+	uint16 x;
+	uint16 y;	
 	const SequenceControl *control;
+	uint16 startupCommand;
+	uint16 finalCommand;
 };
 
-struct ActiveChat {
+struct ActiveText {
 	uint16 strIndex;
 	uint16 x;
 	uint16 y;
 	int duration;
-	uint16 field_8;
-	uint16 startTime;
-	uint16 field_E;
+	uint16 width;
+	uint32 startTime;
+	int16 textcolor;
 };
 
 struct Sequence {
-	uint8 type;
-	const char *filename;
-	int (KyraEngine_v2::*callback)(int);
-	uint8 frameDelay;
+	uint16 flags;
+	const char * wsaFile;
+	const char * cpsFile;
+	uint8 startupCommand;
+	uint8 finalCommand;
+	int16 stringIndex1;
+	int16 stringIndex2;
+	uint16 startFrame;
+	uint16 numFrames;
+	uint16 frameDelay;
+	uint16 xPos;
+	uint16 yPos;
+	int (KyraEngine_v2::*callback)(WSAMovieV2*, int, int, int);
 	uint16 duration;
-	uint8 numFrames;
-	bool timeOut;
-	bool fadeOut;
 };
 
+struct NestedSequence {
+	uint16 flags;
+	const char * wsaFile;
+	uint16 startframe;
+	uint16 endFrame;
+	uint16 frameDelay;
+	int (KyraEngine_v2::*callback)(WSAMovieV2*, int, int, int);
+	uint16 x;
+	uint16 y;
+	const SequenceControl * wsaControl;
+	uint16 startupCommand;
+	uint16 finalCommand;
+	uint16 unk1;
+};
+
 class KyraEngine_v2 : public KyraEngine {
 friend class Debugger_v2;
 friend class TextDisplayer_v2;
@@ -105,36 +162,57 @@
 	virtual void gui_initMainMenu() {}
 	int gui_handleMainMenu();
 	virtual void gui_updateMainMenuAnimation();
-	void gui_drawMainMenu(const char * const *strings, int select);
+	void gui_drawMainMenu(const char *const *strings, int select);
 	void gui_drawMainBox(int x, int y, int w, int h, int fill);
 	bool gui_mainMenuGetInput();
 	
 	void gui_printString(const char *string, int x, int y, int col1, int col2, int flags, ...);
 
-	// intro
+	// intro/outro
 	void seq_playSequences(int startSeq, int endSeq = -1);
-	int seq_introWestwood(int seqNum);
-	int seq_introTitle(int seqNum);
-	int seq_introOverview(int seqNum);
-	int seq_introLibrary(int seqNum);	
-	int seq_introHand(int seqNum);
-	int seq_introPoint(int seqNum);
-	int seq_introZanFaun(int seqNum);
 
-	void seq_introOverviewOver1(int currentFrame);
-	void seq_introOverviewForest(int currentFrame);	
-	void seq_introOverviewDragon(int currentFrame);
-	void seq_loadWSA(int wsaNum, const char *filename, int frameDelay, void (KyraEngine_v2::*callback)(int) = 0, 
-					 const SequenceControl *control = 0 );
+	int seq_introWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introTitle(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introOverview(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introLibrary(WSAMovieV2 *wsaObj, int x, int y, int frm);	
+	int seq_introHand(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introPoint(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introZanfaun(WSAMovieV2 *wsaObj, int x, int y, int frm);
+
+	int seq_introOver1(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introOver2(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introForest(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introDragon(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introDarm(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introLibrary2(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introMarco(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introHand1a(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introHand1b(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introHand1c(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introHand2(WSAMovieV2 *wsaObj, int x, int y, int frm);
+	int seq_introHand3(WSAMovieV2 *wsaObj, int x, int y, int frm);
+
+	void seq_sequenceCommand(int command);
+	void seq_loadNestedSequence(int wsaNum, int seqNum);
+	void seq_nestedSequenceFrame(int command, int wsaNum);
+	void seq_animatedSubFrame(int srcPage, int dstPage, int delaytime,
+		int steps, int x, int y, int w, int h, int openClose, int directionFlags);
+	bool seq_processNextSubFrame(int wsaNum);
+	void seq_resetActiveWSA(int wsaNum);
 	void seq_unloadWSA(int wsaNum);
-	void seq_playWSAs();
-	void seq_showChats();
-	void seq_playIntroChat(uint8 chatNum);
-	void seq_resetAllChatEntries();
-	void seq_waitForChatsToFinish();
-	void seq_setChatEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 unk1);
+	void seq_processWSAs();
+	void seq_cmpFadeFrame(const char *cmpFile);
+	
+	void seq_playTalkText(uint8 chatNum);
+	void seq_resetAllTextEntries();
+	uint32 seq_activeTextsTimeLeft();
+	void seq_waitForTextsTimeout();
+	int seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width);
+	void seq_processText();
+	char *seq_preprocessString(const char *str, int width);
 
-	void mainMenu();
+	void seq_init();
+	void seq_uninit();
 
 	int init();
 	int go();
@@ -143,8 +221,6 @@
 	TextDisplayer_v2 *_text;
 	Debugger_v2 *_debugger;
 	
-	ActiveWSA *_activeWSA;
-	ActiveChat *_activeChat;
 	uint8 *_mouseSHPBuf;
 
 	static const char *_dosSoundFileList[];
@@ -696,9 +772,48 @@
 	int _unk3, _unk4, _unk5;
 	bool _unkSceneScreenFlag1;
 	bool _unkHandleSceneChangeFlag;
+
+	// sequence player
+	ActiveWSA *_activeWSA;
+	ActiveText *_activeText;
+
+	const char *const *_sequenceSoundList;
+	int _sequenceSoundListSize;
+	
+	static const char *_sequenceSoundListPC[];
+	static const int _sequenceSoundListPCSize;
+	static const char *_sequenceStrings[];
+	static const int _sequenceStringsSize;
+	
+	int _sequenceStringsDuration[33];
+
+	uint8 *_pageBuffer1;
+	uint8 *_pageBuffer2;
+	static const uint8 _seqTextColorPresets[];
+	char *_seqProcessedString;
+	WSAMovieV2 *_seqWsa;
+
+	bool _abortIntroFlag;
+	int _menuChoice;
+
+	uint32 _seqFrameDelay;
+	uint32 _seqEndTime;
+	int _seqFrameCounter;
+	bool _seqSubframePlaying;
+	uint8 _seqTextColor[2];
+	
+	static const Sequence _sequences[];
+	static const NestedSequence _nSequences[];
+	static const SequenceControl _wsaControlLibrary[];
+	static const SequenceControl _wsaControlHand1b[];
+	static const SequenceControl _wsaControlHand1c[];
+	static const SequenceControl _wsaControlHand2[];
+	static const SequenceControl _wsaControlHand3[];
+	static const SequenceControl _wsaControlHand4[];
 };
 
 } // end of namespace Kyra
 
 #endif
 
+

Modified: scummvm/trunk/engines/kyra/screen.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/screen.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -2644,8 +2644,9 @@
 		return;
 	}
 
+	const char *ext = filename + strlen(filename) - 3;
 	uint8 compType = srcData[2];
-	uint32 imgSize = READ_LE_UINT32(srcData + 4);
+	uint32 imgSize = scumm_stricmp(ext, "CMP") ? READ_LE_UINT32(srcData + 4) : READ_LE_UINT16(srcData);
 	uint16 palSize = READ_LE_UINT16(srcData + 8);
 
 	if (palData && palSize) {

Modified: scummvm/trunk/engines/kyra/screen_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/screen_v2.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -33,9 +33,11 @@
 Screen_v2::Screen_v2(KyraEngine_v2 *vm, OSystem *system)
 	: Screen(vm, system) {
 	_vm = vm;
+	_wsaFrameAnimBuffer = new uint8[1024];
 }
 
 Screen_v2::~Screen_v2() {
+	delete [] _wsaFrameAnimBuffer;
 }
 
 void Screen_v2::setScreenDim(int dim) {
@@ -60,33 +62,216 @@
 	}
 }
 
-void Screen_v2::k2IntroFadeToGrey(int delay) {
-	debugC(9, kDebugLevelScreen, "Screen_v2::k2IntroFadeToGrey(%d)", delay);
+void Screen_v2::generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag) {
+	uint8 tmpPal[768];
 
-	for (int i = 0; i <= 50; ++i) {
-		if (i <= 8 || i >= 30) {
-			_currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] +
-						      _currentPalette[3 * i + 1] +
-						      _currentPalette[3 * i + 2]) / 3;
-			_currentPalette[3 * i + 1] =  _currentPalette[3 * i + 0];
-			_currentPalette[3 * i + 2] =  _currentPalette[3 * i + 0];
+	for (int i = 0; i != lastColor; i++) {
+		if (flag) {
+			int v = ((((srcPal[3 * i] & 0x3f) + (srcPal[3 * i + 1] & 0x3f)
+				+ (srcPal[3 * i + 2] & 0x3f)) / 3) * factor) / 0x40;
+			tmpPal[3 * i] = tmpPal[3 * i + 1] = tmpPal[3 * i + 2] = v & 0xff;
+		} else {
+			int v = (((srcPal[3 * i] & 0x3f) * factor) / 0x40) + addR;
+			tmpPal[3 * i] = (v > 0x3f) ? 0x3f : v & 0xff;
+			v = (((srcPal[3 * i + 1] & 0x3f) * factor) / 0x40) + addG;
+			tmpPal[3 * i + 1] = (v > 0x3f) ? 0x3f : v & 0xff;
+			v = (((srcPal[3 * i + 2] & 0x3f) * factor) / 0x40) + addB;
+			tmpPal[3 * i + 2] = (v > 0x3f) ? 0x3f : v & 0xff;
 		}
 	}
 
-	// color 71 is the same in both the overview and closeup scenes
-	// Converting it to greyscale makes the trees in the closeup look dull
-	for (int i = 71; i < 200; ++i) {
-		_currentPalette[3 * i + 0] = (_currentPalette[3 * i + 0] +
-					      _currentPalette[3 * i + 1] +
-					      _currentPalette[3 * i + 2]) / 3;
-		_currentPalette[3 * i + 1] =  _currentPalette[3 * i + 0];
-		_currentPalette[3 * i + 2] =  _currentPalette[3 * i + 0];
+	for (int i = 0; i < lastColor; i++)
+		grayOverlay[i] = findLeastDifferentColor(tmpPal + 3 * i, srcPal, lastColor);
+}
+
+void Screen_v2::applyGrayOverlay(int x, int y, int w, int h, int pageNum, const uint8 *grayOverlay) {
+	uint8 * dst = getPagePtr(pageNum) + y * 320 + x;
+	while (h--) {
+		for (int wi = 0; wi < 320; wi++)
+			dst[wi] = grayOverlay[dst[wi]];
+		dst += 320;
 	}
-	fadePalette(_currentPalette, delay);
-	// Make the font color white again
-	setPaletteIndex(254, 254, 254, 254);
 }
 
+int Screen_v2::findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors) {
+	int m = 0x7fff;
+	int r = 0x101;
+
+	for (int i = 0; i < numColors; i++) {
+		int v = paletteEntry[0] - *palette++;
+		int c = v * v;
+		v = paletteEntry[1] - *palette++;
+		c += (v * v);
+		v = paletteEntry[2] - *palette++;
+		c += (v * v);
+
+		if (c <= m) {
+			m = c;
+			r = i;
+		}
+	}
+
+	return r;
+}
+
+void Screen_v2::wsaFrameAnimationStep(int x1, int y1, int x2, int y2,
+	int w1, int h1, int w2, int h2, int srcPage, int dstPage, int dim) {
+
+	if (!(w1 || h1 || w2 || h2))
+		return;
+
+	ScreenDim cdm = _screenDimTable[dim];
+	cdm.sx <<= 3;
+	cdm.w <<= 3;
+
+	int na = 0, nb = 0, nc = w2;
+	
+	if (!calcBounds(cdm.w, cdm.h, x2, y2, w2, h2, na, nb, nc))
+		return;
+
+	uint8 * src = getPagePtr(srcPage) + y1 * 320;
+	uint8 * dst = getPagePtr(dstPage) + (y2 + cdm.sy) * 320;
+
+	int u = -1;
+
+	do {
+		int t = (nb * h1) / h2;
+		if (t != u) {
+			u = t;
+			uint8 * s = src + (x1 + t) * 320;
+			uint8 * dt = (uint8*) _wsaFrameAnimBuffer;
+			
+			t = w2 - w1;
+			if (!t) {
+				memcpy(dt, s, w2);
+			} else if (t > 0) {
+				if (w1 == 1) {
+                    memset(dt, *s, w2);
+				} else {
+					t = ((((((w2 - w1 + 1) & 0xffff) << 8) / w1) + 0x100) & 0xffff) << 8;
+					int bp = 0;
+					for (int i = 0; i < w1; i++) {
+						int cnt = (t >> 16);
+						bp += (t & 0xffff);
+						if (bp > 0xffff) {
+							bp -= 0xffff;
+							cnt++;
+						}
+						memset(dt, *s++, cnt);
+						dt += cnt;						
+					}
+				}
+			} else {
+				if (w2 == 1) {
+					*dt = *s;
+				} else {
+					t = (((((w1 - w2) & 0xffff) << 8) / w2) & 0xffff) << 8;
+					int bp = 0;
+					for (int i = 0; i < w2; i++) {
+						*dt++ = *s++;
+						bp += (t & 0xffff);
+						if (bp > 0xffff) {
+							bp -= 0xffff;
+							s++;
+						}
+						s += (t >> 16);
+					}
+				}
+			}
+		}
+		memcpy(dst + x2 + cdm.sx, _wsaFrameAnimBuffer + na, w2);
+		dst += 320;
+	} while (++nb < h2);	
+}
+
+void Screen_v2::cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage, int dstW,
+	int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage) {
+
+	if (!(cmpW || cmpH ))
+		return;
+
+	int r1, r2, r3, r4, r5, r6;
+
+	int X1 = srcX;
+	int Y1 = srcY;
+	int W1 = cmpW;
+	int H1 = cmpH;
+
+	if (!calcBounds(srcW, srcH, X1, Y1, W1, H1, r1, r2, r3))
+		return;
+
+	int X2 = dstX;
+	int Y2 = dstY;
+	int W2 = W1;
+	int H2 = H1;
+
+	if (!calcBounds(dstW, dstH, X2, Y2, W2, H2, r4, r5, r6))
+		return;
+
+	uint8 * src = getPagePtr(srcPage) + srcW * (Y1 + r5);
+	uint8 * dst = getPagePtr(dstPage) + dstW * (Y2 + r2);
+	uint8 * cmp = getPagePtr(cmpPage);
+
+	while (H2--) {		
+		uint8 * s = src + r4 + X1;
+		uint8 * d = dst + r1 + X2;
+
+		for (int i = 0; i < W2; i++) {
+			int ix = (*s++ << 8) + *d;
+			*d++ = cmp[ix];
+		}
+
+		src += W1;
+		dst += W2;
+	}
+}
+
+bool Screen_v2::calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2) {
+	x2 = 0;
+	y2 = 0;
+	w2 = w1;
+	
+	int t = x1 + w1;
+	if (t < 1) {
+		w1 = h1 = -1;
+	} else {
+		if (t <= x1) {
+			x2 = w1 - t;
+			w1 = t;
+			x1 = 0;
+		}
+		t = w0 - x1;
+		if (t < 1) {
+			w1 = h1 = -1;
+		} else {
+			if (t <= w1) {
+				w1 = t;
+			}
+			w2 -= w1;
+			t = h1 + y1;
+			if (t < 1) {
+				w1 = h1 = -1;
+			} else {
+				if (t <= y1) {
+					y2 = h1 - t;
+					h1 = t;
+					y1 = 0;
+				}
+                t = h0 - y1;
+				if (t < 1) {
+					w1 = h1 = -1;
+				} else {
+					if (t <= h1) {
+						h1 = t;
+					}
+				}
+			}
+		}
+	}
+
+	return (w1 == -1) ? false : true;
+}
+
 void Screen_v2::copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
 							int unk1, const uint8 *unkPtr1, const uint8 *unkPtr2) {
 	uint8 *dstPtr = getPagePtr(_curPage);

Modified: scummvm/trunk/engines/kyra/screen_v2.h
===================================================================
--- scummvm/trunk/engines/kyra/screen_v2.h	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/screen_v2.h	2007-10-19 22:16:00 UTC (rev 29233)
@@ -41,8 +41,15 @@
 	virtual void setScreenDim(int dim);
 	const ScreenDim *getScreenDim(int dim);
 	
-	// palette handling
-	void k2IntroFadeToGrey(int delay=0x54);
+	// sequence player
+	void generateGrayOverlay(const uint8 *srcPal, uint8 *grayOverlay, int factor, int addR, int addG, int addB, int lastColor, bool flag);
+	void applyGrayOverlay(int x, int y, int w, int h, int pageNum, const uint8 *grayOverlay);
+	int findLeastDifferentColor(const uint8 *paletteEntry, const uint8 *palette, uint16 numColors);
+	bool calcBounds(int w0, int h0, int &x1, int &y1, int &w1, int &h1, int &x2, int &y2, int &w2);
+	void wsaFrameAnimationStep(int x1, int y1, int x2, int y2,
+		int w1, int h1, int w2, int h2,	int srcPage, int dstPage, int dim);
+	void cmpFadeFrameStep(int srcPage, int srcW, int srcH, int srcX, int srcY, int dstPage,
+		int dstW, int dstH, int dstX, int dstY, int cmpW, int cmpH, int cmpPage);
 	
 	// screen page handling
 	void copyWsaRect(int x, int y, int w, int h, int dimState, int plotFunc, const uint8 *src,
@@ -74,6 +81,8 @@
 	
 	static const ScreenDim _screenDimTable[];
 	static const int _screenDimTableCount;
+
+	uint8 *_wsaFrameAnimBuffer;
 	
 	// maybe subclass screen for kyra3
 	static const ScreenDim _screenDimTableK3[];

Modified: scummvm/trunk/engines/kyra/sequences_v2.cpp
===================================================================
--- scummvm/trunk/engines/kyra/sequences_v2.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/sequences_v2.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -36,554 +36,1145 @@
 
 void KyraEngine_v2::seq_playSequences(int startSeq, int endSeq) {
 	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playSequences(%i, %i)", startSeq, endSeq);
+	seq_init();
 
-	_skipFlag = false;
+	bool allowSkip = (startSeq == kSequenceTitle) ? false : true;
 
 	if (endSeq == -1)
 		endSeq = startSeq;
 	
-	static const Sequence sequences[] = { 
-		// type, filename, callback, framedelay, duration, numframes, timeOut, fadeOut
-		{2, "virgin.cps",   0,                                 100, 0,   1,  true,  true},
-		{1, "westwood.wsa", &KyraEngine_v2::seq_introWestwood, 6,   160, 18, true,  true},
-		{1, "title.wsa",    &KyraEngine_v2::seq_introTitle,    6,   10,  26, false, false},
-		{2, "over.cps",     &KyraEngine_v2::seq_introOverview, 16,  30,  1,  false, true},
-		{2, "library.cps",  &KyraEngine_v2::seq_introLibrary,  16,  30,  1,  false, true},
-		{2, "hand.cps",     &KyraEngine_v2::seq_introHand,     16,  90,  1,  false, true},
-		{1, "point.wsa",    &KyraEngine_v2::seq_introPoint,    16,  30,  1,  false, true},
-		{1, "zanfaun.wsa",  &KyraEngine_v2::seq_introZanFaun,  16,  90,  1,  false, true}
-	};
+	assert(startSeq >= 0 && endSeq < kSequenceArraySize && startSeq <= endSeq);
 
-	assert(startSeq >= 0 && endSeq < ARRAYSIZE(sequences) && startSeq <= endSeq);
+	_screen->_charWidth = -2;
 
-	_activeWSA = new ActiveWSA[8];
-	assert(_activeWSA);	
 	memset(_activeWSA, 0, sizeof(ActiveWSA) * 8);
+	for (int i = 0; i < 8; i++)
+		_activeWSA[i].flags = -1;
+				
 
-	_activeChat = new ActiveChat[10];
-	assert(_activeChat);	
-	memset(_activeChat, 0, sizeof(ActiveChat) * 10);
+	memset(_activeText, 0, sizeof(ActiveText) * 10);
+	seq_resetAllTextEntries();
 
-	seq_resetAllChatEntries();
-
 	_screen->hideMouse();
 	int oldPage = _screen->setCurPage(2);
-	
-	uint8 pal[768];
-	memset(pal, 0, sizeof(pal));
-	
-	for (int i = startSeq; i <= endSeq && !_skipFlag; i++) {
-		uint32 seqDelay = 0;
-		int seqNum = 0;
 
-		_screen->setScreenPalette(pal);
+	for (int i = 0; i < 4; i++)
+		memset(_screen->getPalette(i), 0, 0x300);
+
+	memset(_pageBuffer1, 0, 0xfa00);
+	memset(_pageBuffer2, 0, 0xfa00);
+
+	_seqSubframePlaying = false;
+	 
+	int seqWsaCurrentFrame = 0;
+	_seqTextColor[0] = _seqTextColor[1] = 0;	
+	_seqEndTime = 0;
+	_menuChoice = 0;
+
+	for (int seqNum = startSeq; seqNum <= endSeq && !((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice); seqNum++) {
 		_screen->clearPage(0);
+		_screen->clearPage(8);
+		memcpy(_screen->getPalette(1), _screen->getPalette(0), 0x300);				
+		_seqFrameCounter = 0;
 
-		if (sequences[i].type == 2) {
-			_screen->loadBitmap(sequences[i].filename, 2, 2, _screen->_currentPalette);
-			_screen->updateScreen();
-			seqDelay = sequences[i].frameDelay * _tickLength;
-		} else if (sequences[i].type == 1) {
-			seq_loadWSA(0, sequences[i].filename, sequences[i].frameDelay);
-			seqDelay = sequences[i].duration * _tickLength;
+		allowSkip = (seqNum == 2) ? false : true;
+		
+		if (_sequences[seqNum].flags & 2) {
+			_screen->loadBitmap(_sequences[seqNum].cpsFile, 2, 2, _screen->getPalette(0));
+		} else {
+			_screen->setCurPage(2);
+			_screen->clearPage(2);
+			_screen->loadPalette("goldfont.col", _screen->getPalette(0));
 		}
 
-		if (sequences[i].callback)
-			(*this.*sequences[i].callback)(seqNum++);
+		if (_sequences[seqNum].callback)
+			(this->*_sequences[seqNum].callback)(0, 0, 0, -1);
 
-		seq_playWSAs();
-		_screen->copyPage(2, 0);
-		_screen->updateScreen();
-		_screen->fadeFromBlack(40);
+		if (_sequences[seqNum].flags & 1) {
+			if (_seqWsa->opened())
+				_seqWsa->close();
+			_seqWsa->open(_sequences[seqNum].wsaFile, 0, _screen->getPalette(0));
+			_seqWsa->setX(_sequences[seqNum].xPos);
+			_seqWsa->setY(_sequences[seqNum].yPos);
+			_seqWsa->setDrawPage(2);
+			_seqWsa->displayFrame(0, 0);
+		}
 
-		seqDelay += _system->getMillis();
-		bool mayEndLoop = sequences[i].timeOut;
+		if (_sequences[seqNum].flags & 4) {
+			int cp = _screen->setCurPage(2);
+			Screen::FontId cf =	_screen->setFont(Screen::FID_GOLDFONT_FNT);
+			int sX = (320 - _screen->getTextWidth(_sequenceStrings[_sequences[seqNum].stringIndex1])) / 2;			
+			_screen->printText(_sequenceStrings[_sequences[seqNum].stringIndex1], sX, 100 - _screen->getFontHeight(), 1, 0);
+			sX = (320 - _screen->getTextWidth(_sequenceStrings[_sequences[seqNum].stringIndex2])) / 2;			
+			_screen->printText(_sequenceStrings[_sequences[seqNum].stringIndex2], sX, 100, 1, 0);
+
+			_screen->setFont(cf);
+			_screen->setCurPage(cp);
+		}
+
+		_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+		_screen->copyPage(0, 2);
+		_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer1);
+		_screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer2);
 		
-		// Skip the movie if esc is pressed or the mouse is clicked
-		// However, don't skip the menu movie, to match the behavior of the original interpreter
-		while ((!_quitFlag && !_skipFlag) || i == kSequenceTitle) {
-			uint32 startTime = _system->getMillis();
+		_screen->copyPage(2, 6);
+		
+		seq_sequenceCommand(_sequences[seqNum].startupCommand);
+		
+		if (!((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+			_screen->copyPage(2, 0);
+			_screen->updateScreen();
+		}		
+
+		if (_sequences[seqNum].flags & 1) {
+			int w2 = _seqWsa->width();
+			int h2 = _seqWsa->height();
+			int x = _sequences[seqNum].xPos;
+			int y = _sequences[seqNum].yPos;
+
+			_seqFrameDelay = _sequences[seqNum].frameDelay;
+
+			if (_seqWsa) {
+				if (x < 0) {
+					x = 0;
+					w2 = 0;
+				}
+
+				if (y < 0) {
+					y = 0;
+					h2 = 0;
+				}
+
+				if (_sequences[seqNum].xPos + _seqWsa->width() > 0x13F)
+					_seqWsa->setWidth(0x140 - _sequences[seqNum].xPos);
+
+				if (_sequences[seqNum].yPos + _seqWsa->height() > 0xC7)
+					_seqWsa->setHeight(0xC7 - _sequences[seqNum].yPos);
+			}
+			uint8 dir = (_sequences[seqNum].startFrame > _sequences[seqNum].numFrames) ? 0 : 1;
+			seqWsaCurrentFrame = _sequences[seqNum].startFrame;
+
+			bool loop = true;
+			while (loop && !((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+				_seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength;
+
+				if (_seqWsa || !_sequences[seqNum].callback)
+					_screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer2);
+
+				if (_sequences[seqNum].callback) {
+					int f = seqWsaCurrentFrame % _seqWsa->frames();
+					(this->*_sequences[seqNum].callback)(_seqWsa, _sequences[seqNum].xPos, _sequences[seqNum].yPos, f);
+				}
+
+				if (_seqWsa) {
+					int f = seqWsaCurrentFrame % _seqWsa->frames();
+					_seqWsa->setX(_sequences[seqNum].xPos);
+					_seqWsa->setY(_sequences[seqNum].yPos);
+					_seqWsa->setDrawPage(2);
+					_seqWsa->displayFrame(f, 0);
+				}
+
+				_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+
+				seq_processWSAs();		
+				seq_processText();
 			
-			if (sequences[i].callback) {
-				int newTime = (*this.*sequences[i].callback)(seqNum++);
-				if (newTime != -1) {
-					seqDelay = newTime * _tickLength + _system->getMillis();
-					mayEndLoop = true;
+				if ((_seqWsa || !_sequences[seqNum].callback) && !((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+					_screen->copyPage(2, 0);
+					_screen->copyPage(2, 6);
+					_screen->updateScreen();
 				}
+				
+				bool loop2 = true;
+				while (loop2 && !((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+					if (_seqWsa) {
+						seq_processText();
+						if (!((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+							_screen->copyPage(2, 0);
+							_screen->copyPage(2, 6);
+							_screen->updateScreen();
+						}
+
+
+						uint32 now = _system->getMillis();
+						if (now >= _seqEndTime) {
+							loop2 = false;
+						} else {
+							uint32 tdiff = _seqEndTime - now;
+							uint32 dly = tdiff < _tickLength ? tdiff : _tickLength;
+							delay(dly);
+							_seqEndTime -= dly;
+						}
+					} else {
+						loop = loop2 = false;
+					}
+				}
+
+				if (loop) {
+					if (dir == 1) {
+						if (++seqWsaCurrentFrame >= _sequences[seqNum].numFrames)
+							loop = false;
+					} else {
+						if (--seqWsaCurrentFrame < _sequences[seqNum].numFrames)
+							loop = false;
+					}
+				}
 			}
+			_seqWsa->close();
+
+
+		} else {
+			_seqFrameDelay = _sequences[seqNum].frameDelay;
+			_seqEndTime = _system->getMillis() + _seqFrameDelay * _tickLength;
+			while (!((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+				uint32 starttime = _system->getMillis();
+				seq_processWSAs();		
+				if (_sequences[seqNum].callback)
+					(this->*_sequences[seqNum].callback)(0, 0, 0, 0);
+				
+				seq_processText();
+	
+				_screen->copyPage(2, 6);		
+				_screen->copyPage(2, 0);
+				_screen->updateScreen();
+				_screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer2);
+
+				uint32 now = _system->getMillis();
+				if (now >= _seqEndTime && !_seqSubframePlaying)
+					break;
+				
+				uint32 tdiff = _seqEndTime - starttime;
+				int32 dly = _tickLength - (now - starttime);
+				if (dly > 0)
+					delay(MIN<uint32>(dly, tdiff));
+			}
+		}
+
+		if (_sequences[seqNum].callback)
+			(this->*_sequences[seqNum].callback)(0, 0, 0, -2);
+
+		uint32 ct = seq_activeTextsTimeLeft();
+		uint32 dl = _sequences[seqNum].duration * _tickLength;
+		if (dl < ct)
+			dl = ct;
+		_seqEndTime = _system->getMillis() + dl;
 		
-			seq_playWSAs();
+		while (!((_skipFlag && allowSkip) || _quitFlag || (_abortIntroFlag && allowSkip) || _menuChoice)) {
+			uint32 starttime = _system->getMillis();
+			seq_processWSAs();
+
+			_screen->copyPage(2, 6);		
 			_screen->copyPage(2, 0);
-			seq_showChats();
 			_screen->updateScreen();
+			_screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer2);
 			
-			uint32 currTime = _system->getMillis();
-			if (seqDelay <= currTime && mayEndLoop) {
+			uint32 now = _system->getMillis();
+			if (now >= _seqEndTime && !_seqSubframePlaying) {
 				break;
 			} else {
-				uint32 loopTime = currTime - startTime;
-				delay(loopTime < _tickLength ? loopTime : _tickLength);
+				uint32 tdiff = _seqEndTime - starttime;
+				delay(MIN<uint32>(tdiff, _tickLength));
 			}
 		}
+		
+		seq_sequenceCommand(_sequences[seqNum].finalCommand);
+		seq_resetAllTextEntries();
 
-		if (sequences[i].fadeOut)
-			_screen->fadeToBlack(40);
+		if ((seqNum != kSequenceTitle && seqNum < kSequenceZanfaun &&
+			(_abortIntroFlag || _skipFlag)) || seqNum == kSequenceZanfaun) {
+			_abortIntroFlag = _skipFlag = false;
+			seqNum = kSequenceWestwood;
+		}
 		
-		if (sequences[i].type == 1)
-			seq_unloadWSA(0);
-		
-		_screen->clearPage(2);
-		
+		if (_menuChoice) {
+			_abortIntroFlag = _skipFlag = false;
+			if (_menuChoice == 2)
+				_menuChoice = 0;
+		}
 	}
+
 	_screen->setCurPage(oldPage);
 	_screen->showMouse();
 
 	for (int i = 0; i < 8; i++)
 		seq_unloadWSA(i);
-	delete[] _activeWSA;
-	delete[] _activeChat;
+
+	if (_seqWsa->opened())
+		_seqWsa->close();
+
+	_screen->_charWidth = 0;
+
+	seq_uninit();
 }
 
-// FIXME: This part needs game dialogs, as it's not part of the intro, but
-// rather a game video. It has speech only in the CD version
-int KyraEngine_v2::seq_introZanFaun(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introZanFaun(%i)", seqNum);
+int KyraEngine_v2::seq_introWestwood(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introWestwood(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm);
+	
+	if (frm == -2)
+		delay(300 * _tickLength);
+	else if (!frm)
+		_sound->playTrack(2);
+	
+	return 0;
+}
 
-	static const SequenceControl zanFaunWSAControl[] = {
-		{0, 6}, {1, 6}, {2, 6}, {3, 6},
-		{4, 6}, {5, 6}, {6, 6}, {7, 6}, 
-		{8, 6}, {9, 6}, {10, 6}, {11, 6}, 
-		{12, 6}, {13, 6}, {14, 6}, {15, 6}, 
-		{16, 6}, {17, 6}, {18, 6}, {19, 6}, 
-		{20, 6}, {21, 6}, {22, 6}, {23, 6}, 
-		{23, 6}, {22, 6}, {21, 6}, {20, 6}, 
-		{19, 6}, {18, 6}, {17, 6}, {16, 6}, 
-		{15, 6}, {14, 6}, {13, 6}, {12, 6}, 
-		{11, 6}, {10, 6}, {9, 6}, {8, 6}, 
-		{7, 6}, {6, 6}, {5, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6},
-		{8, 6}, {9, 6}, {10, 6}, {-1, -1} };
+int KyraEngine_v2::seq_introTitle(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introTitle(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm);
+	
+	if (frm == 1) {
+		_sound->playTrack(3);
+	} else if (frm == 0x19) {
+		int cp = _screen->setCurPage(0);
+		_screen->showMouse();
+		_system->updateScreen();
+		_menuChoice = gui_handleMainMenu() + 1;
+		_seqEndTime = 0;
+		_seqSubframePlaying = false;
+		if (_menuChoice == 4)
+			quitGame();
 
-	switch (seqNum) {
+		_screen->hideMouse();
+		_screen->setCurPage(cp);
+	}
+
+	return 0;
+}
+
+int KyraEngine_v2::seq_introOverview(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introOverview(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm);
+	
+	uint8 * tmpPal = &(_screen->getPalette(3)[0x101]);
+	memset(tmpPal, 0, 256);
+	uint8 txtColorMap[16];
+	uint32 endtime = 0, now = 0;
+
+	switch (_seqFrameCounter) {
 		case 0:
-			_sound->playTrack(8);
-			//XXX: palette stuff
-			//XXX: load dialogs
+			_seqSubframePlaying = true;
+			_sound->playTrack(4);
+			endtime = _system->getMillis() + 60 * _tickLength;
+			
+			_seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+			memset(txtColorMap, _seqTextColor[1], 16);
+			txtColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+
+			_screen->setTextColorMap(txtColorMap);
+		
+			now = _system->getMillis();
+			if (endtime > now)
+				delay(endtime - now);
 			break;
+
 		case 1:
-			seq_loadWSA(1, "zanfaun.wsa", 9, 0, zanFaunWSAControl);
+			_screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x40, 0, 0, 0, 0x100, true);
+			for (int i = 0; i < 256; i++)
+				tmpPal[_screen->getPalette(3)[i]] = 1;
+
+			for (int i = 0; i < 256; i++) {
+				int v = (tmpPal[i] == 1) ? i : _screen->getPalette(3)[i];
+				v *= 3;
+				_screen->getPalette(2)[3 * i] = _screen->getPalette(0)[v];
+				_screen->getPalette(2)[3 * i + 1] = _screen->getPalette(0)[v + 1];
+				_screen->getPalette(2)[3 * i + 2] = _screen->getPalette(0)[v + 2];
+			}
 			break;
-		case 0x294:
-			seq_waitForChatsToFinish();
-			seq_unloadWSA(1);
-			return 0;
+
+		case 40:
+			seq_loadNestedSequence(0, kSequenceOver1);
+			break;
+
+		case 60:
+			seq_loadNestedSequence(1, kSequenceOver2);
+			break;
+
+		case 120:
+			seq_playTalkText(0);
+			break;
+
+		case 200:
+			seq_waitForTextsTimeout();
+			_screen->fadePalette(_screen->getPalette(2), 64);
+			break;
+
+		case 201:
+			_screen->setScreenPalette(_screen->getPalette(2));
+			_screen->updateScreen();
+			_screen->applyGrayOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+			_screen->setScreenPalette(_screen->getPalette(0));
+			_screen->updateScreen();
+			seq_resetActiveWSA(0);
+			seq_resetActiveWSA(1);
+			break;
+
+		case 282:
+			seq_loadNestedSequence(0, kSequenceForest);
+			seq_playTalkText(1);
+			break;
+
+		case 354:
+			seq_resetActiveWSA(0);
+			seq_loadNestedSequence(0, kSequenceDragon);
+			break;
+
+		case 400:
+			seq_waitForTextsTimeout();
+			seq_resetActiveWSA(0);
+			_seqEndTime = 0;
+			_seqSubframePlaying = false;
+			break;
+
 		default:
 			break;
 	}
 
-	return -1;
+	_seqFrameCounter++;
+	return 0;
 }
 
-int KyraEngine_v2::seq_introPoint(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introPoint(%i)", seqNum);
+int KyraEngine_v2::seq_introLibrary(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introLibrary(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm);
+	uint8 txtColorMap[16];
 
-	switch (seqNum) {
+	switch (_seqFrameCounter) {
 		case 0:
-			_sound->playTrack(7);
+			_seqSubframePlaying = true;
+			_sound->playTrack(5);
+			
+			_screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false);
+			_seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+			memset(txtColorMap, _seqTextColor[1], 16);
+			txtColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+
+			_screen->setTextColorMap(txtColorMap);
 			break;
+
 		case 1:
-			seq_loadWSA(1, "point.wsa", 9);
-			seq_playIntroChat(11); // "Zanthia, youngest of the royal mystics has been selected"
+			seq_loadNestedSequence(0, kSequenceLibrary3);
+			seq_playTalkText(4);
 			break;
-		case 0x96:
-			seq_waitForChatsToFinish();
-			seq_unloadWSA(1);
-			return 0;
+
+		case 100:
+			seq_waitForTextsTimeout();
+
+			_screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer2);
+			_screen->applyGrayOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+			_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+			_screen->updateScreen();
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			
+			seq_resetActiveWSA(0);
+			seq_loadNestedSequence(0, kSequenceDarm);
+
+			break;
+
+		case 104:
+			seq_playTalkText(5);
+			break;
+
+		case 240:
+			seq_waitForTextsTimeout();
+			seq_resetActiveWSA(0);
+			seq_loadNestedSequence(0, kSequenceLibrary2);
+			break;
+
+		case 340:
+			seq_resetActiveWSA(0);
+			_screen->applyGrayOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+			_screen->updateScreen();
+
+			seq_loadNestedSequence(0, kSequenceMarco);
+			seq_playTalkText(6);
+			break;
+
+		case 480:
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			seq_waitForTextsTimeout();
+			seq_resetActiveWSA(0);
+			_seqEndTime = 0;
+			_seqSubframePlaying = false;
+			break;
+
 		default:
 			break;
 	}
 
-	return -1;
+	_seqFrameCounter++;
+	return 0;
 }
 
-int KyraEngine_v2::seq_introHand(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introHand(%i)", seqNum);
-	// XXX: commented out to prevent compiler warnings
-	/*static const SequenceControl hand1bWSAControl[] = {
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {5, 6}, {6, 6}, {7, 6},
-		{8, 6}, {9, 6}, {10, 6}, {11, 6}, {11, 12}, {12, 12}, {13, 12}, 
-		{12, 12}, {11, 12}, {-1, -1} };
-	
-	static const SequenceControl hand1cWSAControl[] = {
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6}, {3, 6},
-		{4, 6}, {5, 64}, {5, 6}, {-1, -1} };*/
-	
-	static const SequenceControl hand2WSAControl[] = {
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6},
-		{0, 6}, {1, 6}, {0, 6}, {1, 6}, {0, 6}, {1, 6}, {-1, -1} };
 
-	static const SequenceControl hand3WSAControl[] = {
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {1, 6}, {2, 6}, {1, 6},
-		{0, 6}, {-1, -1} };
+int KyraEngine_v2::seq_introHand(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introHand(%p, %i, %i, %i)", (const void*)wsaObj, x, y, frm);
+	uint8 txtColorMap[16];
 
-	static const SequenceControl hand4WSAControl[] = {
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{0, 6}, {1, 6}, {2, 6}, {3, 6}, {4, 6},
-		{3, 6}, {2, 6}, {1, 6}, {0, 6}, 
-		{-1, -1} };
-	
-	switch (seqNum) {
+	switch (_seqFrameCounter) {
 		case 0:
+			_seqSubframePlaying = true;
 			_sound->playTrack(6);
-			//palette stuff
+			
+			_screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false);
+			_seqTextColor[1] = _screen->findLeastDifferentColor(_seqTextColorPresets, _screen->getPalette(0) + 3, 255) & 0xff;
+			memset(txtColorMap, _seqTextColor[1], 16);
+			txtColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+
+			_screen->setTextColorMap(txtColorMap);
 			break;
+
 		case 1:
-			// XXX: these show as garbage. New frame encode?
-			/*seq_loadWSA(1, "hand1a.wsa", 9);
-			seq_loadWSA(2, "hand1b.wsa", 9, 0, hand1bWSAControl);
-			seq_loadWSA(3, "hand1c.wsa", 9, 0, hand1cWSAControl);*/
-			seq_playIntroChat(7); // "Luckily, the Hand was experienced in these matters"
+			seq_loadNestedSequence(0, kSequenceHand1a);
+			seq_loadNestedSequence(1, kSequenceHand1b);
+			seq_loadNestedSequence(2, kSequenceHand1c);
+			seq_playTalkText(7);
 			break;
-		case 0xc9:
-			// palette stuff
-			seq_loadWSA(4, "hand2.wsa", 9, 0, hand2WSAControl);
-			seq_waitForChatsToFinish();
-			seq_playIntroChat(8); // "and finally, a plan was approved"
+
+		case 201:
+			seq_waitForTextsTimeout();
+			_screen->applyGrayOverlay(0, 0, 320, 200, 2, _screen->getPalette(3));
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+			_screen->updateScreen();
+			seq_resetActiveWSA(0);
+			seq_resetActiveWSA(1);
+			seq_resetActiveWSA(2);
+			seq_loadNestedSequence(0, kSequenceHand2);
+			seq_playTalkText(8);
 			break;
-		case 0x18b:
-			seq_loadWSA(5, "hand3.wsa", 9, 0, hand3WSAControl);
-			seq_waitForChatsToFinish();
-			seq_playIntroChat(9); // "which required a magic anchorstone"
+
+		case 260:
+			seq_waitForTextsTimeout();
+			seq_resetActiveWSA(0);
+			seq_loadNestedSequence(1, kSequenceHand3);
+			seq_playTalkText(9);
 			break;
-		case 0x1f4:
-			seq_loadWSA(6, "hand4.wsa", 9, 0, hand4WSAControl);
-			seq_waitForChatsToFinish();
-			seq_playIntroChat(10); // "to be retrieved from the center of the world"
+
+		case 365:
+			seq_waitForTextsTimeout();
+			seq_resetActiveWSA(1);
+			seq_loadNestedSequence(0, kSequenceHand4);
 			break;
-		case 0x320:
-			seq_waitForChatsToFinish();
-			/*seq_unloadWSA(1);
-			seq_unloadWSA(2);	
-			seq_unloadWSA(3);*/
-			seq_unloadWSA(4);
-			seq_unloadWSA(5);
-			seq_unloadWSA(6);						
-			return 0;
+
+		case 405:
+			seq_playTalkText(10);
+			break;
+
+		case 484:
+			seq_waitForTextsTimeout();
+			seq_resetActiveWSA(0);
+			_seqEndTime = 0;
+			_seqSubframePlaying = false;
+			break;
+
+		default:
+			break;
 	}
-	
-	return -1;
+
+	_seqFrameCounter++;
+	return 0;
 }
 
-int KyraEngine_v2::seq_introLibrary(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introLibrary(%i)", seqNum);
-	
-	static const SequenceControl libraryWSAControl[] = {
-		{0, 10}, {1, 10}, {2, 10}, {3, 10}, {4, 10}, {5, 10}, {6, 10}, {7, 10},
-		{8, 10}, {9, 10}, {8, 10}, {7, 10}, {6, 10}, {5, 40}, {4, 10}, {3, 10},
-		{2, 10}, {1, 10}, {-1, -1} };
-	
-	switch (seqNum) {
+int KyraEngine_v2::seq_introPoint(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == -2) {
+		seq_waitForTextsTimeout();
+		_seqEndTime = 0;
+	}
+
+	uint8 txtColorMap[16];
+
+	switch (_seqFrameCounter) {
+		case -2:
+			seq_waitForTextsTimeout();
+			break;
+
 		case 0:
-			_sound->playTrack(5);
-			seq_playIntroChat(4); // "The royal mystics are baffled"
-			//XXX: palette stuff
+			_sound->playTrack(7);			
+			
+			_seqTextColor[1] = 0xf7;
+			memset(txtColorMap, _seqTextColor[1], 16);
+			txtColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+			_screen->setTextColorMap(txtColorMap);
+			_screen->generateGrayOverlay(_screen->getPalette(0), _screen->getPalette(3), 0x24, 0, 0, 0, 0x100, false);
 			break;
+
 		case 1:
-			seq_loadWSA(1, "library.wsa", 9, 0, libraryWSAControl);
+			seq_playTalkText(11);
 			break;
-		case 0x64:
-			seq_waitForChatsToFinish();
-			// unk1 = 7;
-			// palette/screen stuff
-			seq_loadWSA(2, "darm.wsa", 9);
-			break;
-		case 0x68:
-			seq_waitForChatsToFinish();
-			seq_playIntroChat(5);  // "Every reference has been consulted"
-			break;
-		case 0xF0:
-			seq_waitForChatsToFinish();
-			seq_loadWSA(3, "library.wsa", 9);
-			break;
-		case 0x154:
-			seq_waitForChatsToFinish();
-			// palette stuff
-			seq_loadWSA(4, "marco.wsa", 9);
-			seq_playIntroChat(6); // "Even Marko and his new valet have been allowed"
-			break;
-		case 0x294:
-			seq_waitForChatsToFinish();
-			seq_unloadWSA(1);
-			seq_unloadWSA(2);
-			seq_unloadWSA(3);
-			seq_unloadWSA(4);
-			return 0;
+
 		default:
 			break;
 	}
 
-	return -1;
+	_seqFrameCounter++;
+	return 0;
 }
 
-int KyraEngine_v2::seq_introOverview(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introOverview(%i)", seqNum);
-	
-	switch (seqNum) {
+int KyraEngine_v2::seq_introZanfaun(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == -2) {
+		seq_waitForTextsTimeout();
+		_seqEndTime = 0;
+		return 0;
+	}
+
+	uint8 txtColorMap[16];
+
+	switch (_seqFrameCounter) {
 		case 0:
-			_sound->playTrack(4);
+			_sound->playTrack(8);			
+			
+			_seqTextColor[1] = 0xfd;
+			memset(txtColorMap, _seqTextColor[1], 16);
+			txtColorMap[1] = _seqTextColor[0] = _screen->findLeastDifferentColor(_seqTextColorPresets + 3, _screen->getPalette(0) + 3, 255) & 0xff;
+			_screen->setTextColorMap(txtColorMap);
 			break;
-		case 40:
-			seq_loadWSA(1, "over1.wsa", 10, &KyraEngine_v2::seq_introOverviewOver1);
+
+		case 1:
+			seq_setTextEntry(21, 140, 70, 20, 160);
+			if (_flags.isTalkie)
+				_sound->voicePlay(_sequenceSoundList[13]);
+			_seqFrameDelay = 200;
 			break;
-		case 60:
-			seq_loadWSA(2, "over2.wsa", 9);
+
+		case 2:
+		case 11:
+		case 21:
+			_seqFrameDelay = 12;
 			break;
-		case 120:
-			seq_playIntroChat(0); // "Kyrandia is disappearing!"
+
+		case 10:
+			seq_waitForTextsTimeout();
+			seq_setTextEntry(13, 140, 50, _sequenceStringsDuration[13], 160);
+			if (_flags.isTalkie)
+				_sound->voicePlay(_sequenceSoundList[14]);
+			_seqFrameDelay = 300;
 			break;
-		case 200:
-			seq_waitForChatsToFinish();
-			// XXX: fade to grey
-			_screen->k2IntroFadeToGrey(40);
+
+		case 20:
+			seq_setTextEntry(18, 160, 50, _sequenceStringsDuration[17], 160);
+			if (_flags.isTalkie)
+				_sound->voicePlay(_sequenceSoundList[15]);
+			_seqFrameDelay = 200;
+		break;
+
+		case 19:
+		case 26:
+			seq_waitForTextsTimeout();
 			break;
-		case 201:
-			// XXX
+
+		case 46:
+			seq_waitForTextsTimeout();
+			seq_setTextEntry(16, 200, 50, _sequenceStringsDuration[16], 120);
+			if (_flags.isTalkie)
+				_sound->voicePlay(_sequenceSoundList[16]);
+			_seqEndTime = _system->getMillis() + 120 * _tickLength;
 			break;
-		case 282:
-			seq_waitForChatsToFinish();
-			seq_loadWSA(3, "forest.wsa", 6,  &KyraEngine_v2::seq_introOverviewForest);
-			seq_playIntroChat(1); // "Rock by rock..."
+
+		default:
 			break;
-		case 434:
-			seq_waitForChatsToFinish();
-			seq_loadWSA(4, "dragon.wsa", 6,  &KyraEngine_v2::seq_introOverviewDragon);
-			break;
-		case 540:
-			seq_waitForChatsToFinish();
-			seq_unloadWSA(1);
-			seq_unloadWSA(2);
-			seq_unloadWSA(3);
-			seq_unloadWSA(4);
-			return 0;
-			break;	
+	}	
+	
+	_seqFrameCounter++;
+	return 0;
+}
+
+int KyraEngine_v2::seq_introOver1(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 2)
+		seq_waitForTextsTimeout();
+	else if (frm == 3)
+		seq_playTalkText(12);
+	return frm;
+}
+
+
+int KyraEngine_v2::seq_introOver2(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 1)
+		seq_playTalkText(12);
+	return frm;
+}
+
+int KyraEngine_v2::seq_introForest(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 11)
+		seq_waitForTextsTimeout();
+	else if (frm == 12)
+		seq_playTalkText(2);
+	return frm;
+}
+
+int KyraEngine_v2::seq_introDragon(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 11)
+		seq_waitForTextsTimeout();
+	else if (frm == 3)
+		seq_playTalkText(3);
+	return frm;
+}
+
+int KyraEngine_v2::seq_introDarm(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	//NULLSUB (at least in fm-towns version)
+	return frm;
+}
+
+int KyraEngine_v2::seq_introLibrary2(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	//NULLSUB (at least in fm-towns version)
+	return frm;
+}
+
+int KyraEngine_v2::seq_introMarco(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 36) {
+		seq_waitForTextsTimeout();
+		_seqEndTime = 0;
 	}
+	return frm;
+}
 
-	return -1;
+int KyraEngine_v2::seq_introHand1a(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	//NULLSUB (at least in fm-towns version)
+	return frm;
 }
 
-void KyraEngine_v2::seq_introOverviewOver1(int currentFrame) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introOverviewOver1(%i)", currentFrame);
-	
-	if (currentFrame == 2)
-		seq_waitForChatsToFinish();
-	else if (currentFrame == 3)
-		seq_playIntroChat(12);
+int KyraEngine_v2::seq_introHand1b(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 15)
+		frm = 12;
+	return frm;
 }
 
-void KyraEngine_v2::seq_introOverviewForest(int currentFrame) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introOverviewForest(%i)", currentFrame);
-	
-	if (currentFrame == 11) {
-		seq_waitForChatsToFinish();
-	} else if (currentFrame == 12) {
-		delay(25);
-		seq_playIntroChat(2); // "...and tree by tree..."
+int KyraEngine_v2::seq_introHand1c(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	if (frm == 8)
+		frm = 4;
+	return frm;
+}
+
+int KyraEngine_v2::seq_introHand2(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	//NULLSUB (at least in fm-towns version)
+	return frm;
+}
+
+int KyraEngine_v2::seq_introHand3(WSAMovieV2 *wsaObj, int x, int y, int frm) {
+	//NULLSUB (at least in fm-towns version)
+	return frm;
+}
+
+uint32 KyraEngine_v2::seq_activeTextsTimeLeft() {
+	uint32 res = 0;
+
+	for (int i = 0; i < 10; i++) {
+		uint32 chatend = (_activeText[i].duration + _activeText[i].startTime);
+		uint32 curtime = _system->getMillis();
+		if (_activeText[i].duration != -1 && chatend > curtime) {
+			chatend -= curtime;
+			if (res < chatend)
+				res = chatend;
+		}
 	}
+
+	return res;
 }
 
-void KyraEngine_v2::seq_introOverviewDragon(int currentFrame) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introOverviewDragon(%i)", currentFrame);
-	
-	if (currentFrame == 3)
-		seq_playIntroChat(3); // "Kyrandia ceases to exist!"
-	else if (currentFrame == 11)
-		seq_waitForChatsToFinish();
+void KyraEngine_v2::seq_processWSAs() {
+	for (int i = 0; i <  8; i++) {
+		if (_activeWSA[i].flags != -1) {
+			if (seq_processNextSubFrame(i))
+				seq_resetActiveWSA(i);
+		}
+	}
 }
 
-int KyraEngine_v2::seq_introTitle(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introtitle(%i)", seqNum);
-	
-	if (seqNum == 1) {
-		_sound->playTrack(3);
-	} else if (seqNum == 25) {
-		// XXX: handle menu
-		return 200;
+void KyraEngine_v2::seq_processText() {
+	Screen::FontId curFont = _screen->setFont(Screen::FID_GOLDFONT_FNT);
+	int curPage = _screen->setCurPage(2);
+	char outputStr[60];
+
+	for (int i = 0; i < 10; i++) {
+		if (_activeText[i].startTime + _activeText[i].duration > _system->getMillis() && _activeText[i].duration != -1) {
+
+			char *srcStr = seq_preprocessString(_sequenceStrings[_activeText[i].strIndex], _activeText[i].width);
+			int yPos = _activeText[i].y;
+
+			while (*srcStr) {
+				uint32 linePos = 0;
+				for (; *srcStr; linePos++) {
+					if (*srcStr == 0x0d) // Carriage return
+						break;
+					outputStr[linePos] = *srcStr;
+					srcStr++;
+				}
+                outputStr[linePos] = 0;
+				if (*srcStr == 0x0d)
+					srcStr++;
+
+				uint8 textColor = (_activeText[i].textcolor >= 0) ? _activeText[i].textcolor : _seqTextColor[0];
+				_screen->printText(outputStr, _activeText[i].x - (_screen->getTextWidth(outputStr) / 2), yPos, textColor, 0);
+				yPos += 10;
+			}
+		} else {
+			_activeText[i].duration = -1;
+		}
 	}
 
-	return -1;
+	_screen->setCurPage(curPage);
+	_screen->setFont(curFont);
 }
 
-int KyraEngine_v2::seq_introWestwood(int seqNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_introWestwood(%i)", seqNum);
+char *KyraEngine_v2::seq_preprocessString(const char *srcStr, int width) {
+	char *dstStr = _seqProcessedString;
+	int lineStart = 0;
+	int linePos = 0;
 	
-	if (seqNum == 0)
-		_sound->playTrack(2);
+	while (*srcStr) {
+		while (*srcStr && *srcStr != 0x20) // Space
+			dstStr[lineStart + linePos++] = *srcStr++;
+		dstStr[lineStart + linePos] = 0;
 
-	return -1;
+		int len = _screen->getTextWidth(&dstStr[lineStart]);
+		if (width >= len && *srcStr) {
+			dstStr[lineStart + linePos++] = *srcStr++;			
+		} else {
+			dstStr[lineStart + linePos] = 0x0d; // Carriage return
+			lineStart += linePos + 1;
+			linePos = 0;
+			if (*srcStr)
+				srcStr++;
+		}
+	}
+	dstStr[lineStart + linePos] = 0;
+	
+	return strlen(_seqProcessedString) ? dstStr : 0;
 }
 
-void KyraEngine_v2::seq_playIntroChat(uint8 chatNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playIntroChat(%i)", chatNum);
+void KyraEngine_v2::seq_sequenceCommand(int command) {
+	uint8 pal[768];
+    
+	for (int i = 0; i < 8; i++)
+		seq_resetActiveWSA(i);
 	
-	assert(chatNum < _introSoundListSize);
+	switch (command) {
+		case 0:
+			memset(pal, 0, 0x300);
+			_screen->fadePalette(pal, 16);
+			memcpy (_screen->getPalette(0), pal, 0x300);
+			memcpy (_screen->getPalette(1), pal, 0x300);
+			break;
+
+		case 1:
+			memset(pal, 0x3F, 0x300);
+			//////////TODO
+			//////////Unused anyway (at least by fm-towns intro/outro)
+
+			_screen->fadePalette(pal, 16);
+			memcpy (_screen->getPalette(0), pal, 0x300);
+			memcpy (_screen->getPalette(1), pal, 0x300);
+			break;
+
+		case 3:
+			_screen->copyPage(2, 0);
+			_screen->fadePalette(_screen->getPalette(0), 16);
+			memcpy (_screen->getPalette(1), _screen->getPalette(0), 0x300);
+			break;
+
+		case 4:
+			_screen->copyPage(2, 0);
+			_screen->fadePalette(_screen->getPalette(0), 36);
+			memcpy (_screen->getPalette(1), _screen->getPalette(0), 0x300);
+			break;
+
+		case 5:
+			_screen->copyPage(2, 0);
+			break;
 	
-	if (chatNum < 12)
-		seq_setChatEntry(chatNum, 160, 168, _introStringsDuration[chatNum], 160);
-	_sound->voicePlay(_introSoundList[chatNum]);
-}
+		case 6:
+			// UNUSED
+			// seq_loadBLD("library.bld");
+			break;
 
-void KyraEngine_v2::seq_waitForChatsToFinish() {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_waitForChatsToFinish()");
+		case 7:
+			// UNUSED
+			// seq_loadBLD("marco.bld");
+			break;
 	
-	uint32 longest = 0;
+		case 8:
+			memset(pal, 0, 0x300);
+			_screen->fadePalette(pal, 16);
+			memcpy (_screen->getPalette(0), pal, 0x300);
+			memcpy (_screen->getPalette(1), pal, 0x300);
+
+			delay(120 * _tickLength);
+			break;
 	
-	for (int i = 0; i < 10; i++) {
-		if (_activeChat[i].duration != -1) {
-			uint32 currChatTime = _activeChat[i].duration + _activeChat[i].startTime;
-			if ( currChatTime > longest)
-				longest = currChatTime;
-		}
+		case 9:
+			for (int i = 0; i < 0x100; i++) {
+				int pv = (_screen->getPalette(0)[3 * i] + _screen->getPalette(0)[3 * i + 1] + _screen->getPalette(0)[3 * i + 2]) / 3;
+				pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = pv & 0xff;
+			}
+
+			//int a = 0x100;
+			//int d = (0x800 << 5) - 0x100;
+			//pal[3 * i] = pal[3 * i + 1] = pal[3 * i + 2] = 0x3f;
+
+			_screen->fadePalette(pal, 64);
+			memcpy (_screen->getPalette(0), pal, 0x300);
+			memcpy (_screen->getPalette(1), pal, 0x300);
+			break;
+
+		default:
+			break;
 	}
+}
 
+void KyraEngine_v2::seq_cmpFadeFrame(const char * cmpFile) {
+	_screen->copyBlockToPage(2, 0, 0, 320, 200, _pageBuffer1);
+	_screen->copyRegionToBuffer(4, 0, 0, 320, 200, _pageBuffer1);
+	_screen->clearPage(6);
+	_screen->loadBitmap(cmpFile, 6, 6, 0);
+	_screen->copyBlockToPage(4, 0, 0, 320, 200, _pageBuffer2);
+
+	for (int i = 0; i < 3; i++) {
+		uint32 endtime = _system->getMillis() + 4 * _tickLength;
+		_screen->cmpFadeFrameStep(4, 320, 200, 0, 0, 2, 320, 200, 0, 0, 320, 200, 6);
+		_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0);
+		_screen->updateScreen();
+        delayUntil(endtime);
+	}
+
+	_screen->copyPage(4, 0);
+	_screen->updateScreen();
+	_screen->copyPage(4, 2);
+	_screen->copyPage(4, 6);
+	_screen->copyBlockToPage(4, 0, 0, 320, 200, _pageBuffer1);
+}
+
+void KyraEngine_v2::seq_playTalkText(uint8 chatNum) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playIntroChat(%i)", chatNum);
+	
+	assert(chatNum < _sequenceSoundListSize);
+
+	if (chatNum < 12)
+		seq_setTextEntry(chatNum, 160, 168, _sequenceStringsDuration[chatNum], 160);
+
+	_sound->voicePlay(_sequenceSoundList[chatNum]);
+}
+
+void KyraEngine_v2::seq_waitForTextsTimeout() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_waitForTextsTimeout()");
+	
+	uint32 longest = seq_activeTextsTimeLeft() + _system->getMillis();
 	uint32 now = _system->getMillis();
 	if (longest > now)
 		delay(longest - now);
+
+	seq_resetAllTextEntries();
 }
 
-void KyraEngine_v2::seq_resetAllChatEntries() {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_resetAllChatEntries()");
-	
+void KyraEngine_v2::seq_resetAllTextEntries() {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_resetAllTextEntries()");
 	for (int i = 0; i < 10; i++)
-		_activeChat[i].duration = -1;
+		_activeText[i].duration = -1;
 }
 
-void KyraEngine_v2::seq_setChatEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 unk1) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_setChatEntry(%i, %i, %i, %i, %i)", strIndex, posX, posY, duration, unk1);
+int KyraEngine_v2::seq_setTextEntry(uint16 strIndex, uint16 posX, uint16 posY, int duration, uint16 width) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_setTextEntry(%i, %i, %i, %i, %i)", strIndex, posX, posY, duration, width);
 	
 	for (int i = 0; i < 10; i++) {
-		if (_activeChat[i].duration != -1)
-			continue;
+		if (_activeText[i].duration != -1) {
+			if (i < 9)
+				continue;
+			else
+				return -1;
+		}
 
-		_activeChat[i].strIndex = strIndex;
-		_activeChat[i].x = posX;
-		_activeChat[i].y = posY;
-		_activeChat[i].duration = duration * _tickLength;
-		_activeChat[i].field_8 = unk1;
-		_activeChat[i].startTime = _system->getMillis();
+		_activeText[i].strIndex = strIndex;
+		_activeText[i].x = posX;
+		_activeText[i].y = posY;
+		_activeText[i].duration = duration * _tickLength;
+		_activeText[i].width = width;
+		_activeText[i].startTime = _system->getMillis();
+		_activeText[i].textcolor = -1;		
 
-		return;
+		return i;
 	}
+	return -1;
 }
 
-void KyraEngine_v2::seq_showChats() {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_showChats()");
+void KyraEngine_v2::seq_loadNestedSequence(int wsaNum, int seqNum) {
+	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_loadNestedSequence(%i, %i)", wsaNum, seqNum);
+
+	if (_activeWSA[wsaNum].flags != -1)
+		return;
 	
-	uint32 now = _system->getMillis();
+	NestedSequence s = _nSequences[seqNum];
+	
+	if (!_activeWSA[wsaNum].movie) {
+		_activeWSA[wsaNum].movie = new WSAMovieV2(this);	
+		assert(_activeWSA[wsaNum].movie);
+	}
 
-	for (int i = 0; i < 10; i++) {
-		if (_activeChat[i].duration != -1) {
-			if ((_activeChat[i].startTime + (uint32)_activeChat[i].duration) > now) {
-				assert(_activeChat[i].strIndex < _introStringsSize);
-				
-				_text->printIntroTextMessage(_introStrings[_activeChat[i].strIndex], _activeChat[i].x, _activeChat[i].y + 12,
-					0xfe, 150 /*_activeChat[i].field_8*/, 0x0, 0, Screen::FID_GOLDFONT_FNT);
-			} else
-				_activeChat[i].duration = -1;
-		}
+	if (_activeWSA[wsaNum].movie->opened())
+		_activeWSA[wsaNum].movie->close();
+
+	_activeWSA[wsaNum].movie->open(s.wsaFile, 0, 0);
+
+	if (!_activeWSA[wsaNum].movie->opened()) {
+		delete _activeWSA[wsaNum].movie;
+		_activeWSA[wsaNum].movie = 0;
+		return;
 	}
-}
 
-void KyraEngine_v2::seq_playWSAs() {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_playWSAs()");
+	_activeWSA[wsaNum].endFrame = s.endFrame;
+	_activeWSA[wsaNum].startFrame = _activeWSA[wsaNum].currentFrame = s.startframe;
+	_activeWSA[wsaNum].frameDelay = s.frameDelay;
+	_activeWSA[wsaNum].movie->setX(0);
+	_activeWSA[wsaNum].movie->setY(0);	
+	_activeWSA[wsaNum].movie->setDrawPage(_screen->_curPage);
+	_activeWSA[wsaNum].callback = s.callback;	
+	_activeWSA[wsaNum].control = s.wsaControl;
+
+	_activeWSA[wsaNum].flags = s.flags | 1;
+	_activeWSA[wsaNum].x = s.x;
+	_activeWSA[wsaNum].y = s.y;
+	_activeWSA[wsaNum].startupCommand = s.startupCommand;
+	_activeWSA[wsaNum].finalCommand = s.finalCommand;
+	_activeWSA[wsaNum].lastFrame = 0xffff;
 	
-	uint32 currTime = _system->getMillis();
+	seq_nestedSequenceFrame(s.startupCommand, wsaNum);
 
-	for (int i = 0; i < 8; i++) {
-			int currentFrame, frameDelay;
+	if (!s.startupCommand)
+		seq_processNextSubFrame(wsaNum);
 
-			if (_activeWSA[i].control) {
-				int8 nextFrame = _activeWSA[i].control[_activeWSA[i].currentFrame].frameIndex;
-				if (nextFrame == -1)
-					continue;
-				
-				currentFrame = nextFrame;
-				frameDelay = _activeWSA[i].control[_activeWSA[i].currentFrame].frameDelay;				
-			} else {
-				if (_activeWSA[i].currentFrame >= _activeWSA[i].endFrame)
-					continue;				
+	_activeWSA[wsaNum].nextFrame = _system->getMillis();
+}
 
-				currentFrame = _activeWSA[i].currentFrame;
-				frameDelay = _activeWSA[i].frameDelay;
-			}
+void KyraEngine_v2::seq_nestedSequenceFrame(int command, int wsaNum) {
+	int xa = 0, ya = 0;
+	command--;
+	if (!_activeWSA[wsaNum].movie)
+		return;
 
-			_activeWSA[i].movie->displayFrame(currentFrame);
+	switch (command) {
+		case 0:
+			_activeWSA[wsaNum].movie->setDrawPage(8);
+			xa = -_activeWSA[wsaNum].movie->xAdd();
+			ya = -_activeWSA[wsaNum].movie->yAdd();
+			_activeWSA[wsaNum].movie->setX(xa);
+			_activeWSA[wsaNum].movie->setY(ya);
+			_activeWSA[wsaNum].movie->displayFrame(0, 0);
+			_activeWSA[wsaNum].movie->setX(0);
+			_activeWSA[wsaNum].movie->setY(0);
+			seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
+								_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 2);
+			break;
 
-			if (_activeWSA[i].movie && currTime >= _activeWSA[i].nextFrame) {
-				if (_activeWSA[i].callback != 0)
-					(*this.*_activeWSA[i].callback)(currentFrame);
-				_activeWSA[i].currentFrame++;
-				_activeWSA[i].nextFrame = currTime + frameDelay * _tickLength;
-			}
+		case 1:
+			_activeWSA[wsaNum].movie->setDrawPage(8);
+			xa = -_activeWSA[wsaNum].movie->xAdd();
+			ya = -_activeWSA[wsaNum].movie->yAdd();
+			_activeWSA[wsaNum].movie->setX(xa);
+			_activeWSA[wsaNum].movie->setY(ya);
+			_activeWSA[wsaNum].movie->displayFrame(0, 0);
+			_activeWSA[wsaNum].movie->setX(0);
+			_activeWSA[wsaNum].movie->setY(0);
+			seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
+								_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 1, 1);
+			break;	
+
+		case 2:
+			seq_waitForTextsTimeout();
+			_activeWSA[wsaNum].movie->setDrawPage(8);
+			xa = -_activeWSA[wsaNum].movie->xAdd();
+			ya = -_activeWSA[wsaNum].movie->yAdd();
+			_activeWSA[wsaNum].movie->setX(xa);
+			_activeWSA[wsaNum].movie->setY(ya);
+			_activeWSA[wsaNum].movie->displayFrame(0x15, 0);
+			_activeWSA[wsaNum].movie->setX(0);
+			_activeWSA[wsaNum].movie->setY(0);
+			seq_animatedSubFrame(8, 2, 7, 8, _activeWSA[wsaNum].movie->xAdd(), _activeWSA[wsaNum].movie->yAdd(),
+						     	_activeWSA[wsaNum].movie->width(), _activeWSA[wsaNum].movie->height(), 0, 2);
+			break;
+
+		case 3:
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer1);
+			_activeWSA[wsaNum].movie->setDrawPage(2);
+			_activeWSA[wsaNum].movie->setX(0);
+			_activeWSA[wsaNum].movie->setY(0);
+			_activeWSA[wsaNum].movie->displayFrame(0, 0);
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			seq_cmpFadeFrame("scene2.cmp");
+			break;
+
+		case 4:
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer1);
+			_activeWSA[wsaNum].movie->setDrawPage(2);
+			_activeWSA[wsaNum].movie->setX(0);
+			_activeWSA[wsaNum].movie->setY(0);
+			_activeWSA[wsaNum].movie->displayFrame(0, 0);
+			_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+			seq_cmpFadeFrame("scene3.cmp");
+			break;
+
+		default:
+			break;
 	}
 }
 
-void KyraEngine_v2::seq_loadWSA(int wsaNum, const char *filename, int frameDelay,
-								void (KyraEngine_v2::*callback)(int), const SequenceControl *control) {
+void KyraEngine_v2::seq_animatedSubFrame(int srcPage, int dstPage, int delaytime, int steps, 
+                                         int x, int y, int w, int h, int openClose, int directionFlags) {
+		
+	if (openClose) {
+		for (int i = 1; i < steps; i++) {
+			uint32 endtime = _system->getMillis() + delaytime * _tickLength;
 
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_loadWSA(%i, %s, %i, %i)", wsaNum, filename, frameDelay, callback ? true : false);
-	
-	_activeWSA[wsaNum].movie = new WSAMovieV2(this);
-	assert(_activeWSA[wsaNum].movie);
-	_activeWSA[wsaNum].endFrame = _activeWSA[wsaNum].movie->open(filename, 0, _screen->_currentPalette);
-	_activeWSA[wsaNum].movie->flagOldOff(true);
-	assert(_activeWSA[wsaNum].movie->opened());
-	_activeWSA[wsaNum].currentFrame = 0;
-	_activeWSA[wsaNum].frameDelay = frameDelay;
-	_activeWSA[wsaNum].nextFrame = _system->getMillis();
-	_activeWSA[wsaNum].movie->setX(0);
-	_activeWSA[wsaNum].movie->setY(0);	
-	_activeWSA[wsaNum].movie->setDrawPage(_screen->_curPage);
-	_activeWSA[wsaNum].callback = callback;	
-	_activeWSA[wsaNum].control = control;
+			int w2 = (((w * 256) / steps) * i) / 256;
+			int h2 = (((h * 256) / steps) * i) / 256;
+
+			int ym = (directionFlags & 2) ? (h - h2) : 0;
+			int xm = (directionFlags & 1) ? (w - w2) : 0;
+
+			_screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0);
+
+			_screen->copyPage(dstPage, 6);
+			_screen->copyPage(dstPage, 0);
+			_screen->updateScreen();
+
+			_screen->copyBlockToPage(dstPage, 0, 0, 320, 200, _pageBuffer2);
+			delayUntil(endtime);
+		}
+
+		_screen->wsaFrameAnimationStep(0, 0, x, y, w, h, w, h, srcPage, dstPage, 0);
+		_screen->copyPage(dstPage, 6);
+		_screen->copyPage(dstPage, 0);
+		_screen->updateScreen();
+	} else {
+		_screen->copyBlockToPage(dstPage, 0, 0, 320, 200, _pageBuffer2);
+		for (int i = steps; i; i--) {
+			uint32 endtime = _system->getMillis() + delaytime * _tickLength;
+
+			int w2 = (((w * 256) / steps) * i) / 256;
+			int h2 = (((h * 256) / steps) * i) / 256;
+
+			int ym = (directionFlags & 2) ? (h - h2) : 0;
+			int xm = (directionFlags & 1) ? (w - w2) : 0;
+
+			_screen->wsaFrameAnimationStep(0, 0, x + xm, y + ym, w, h, w2, h2, srcPage, dstPage, 0);
+
+			_screen->copyPage(dstPage, 6);
+			_screen->copyPage(dstPage, 0);
+			_screen->updateScreen();
+
+			_screen->copyBlockToPage(dstPage, 0, 0, 320, 200, _pageBuffer2);
+			delayUntil(endtime);
+		}
+	}
 }
 
+void KyraEngine_v2::seq_resetActiveWSA(int wsaNum) {
+	if (_activeWSA[wsaNum].flags == -1)
+		return;
+
+	_activeWSA[wsaNum].flags = -1;
+	seq_nestedSequenceFrame(_activeWSA[wsaNum].finalCommand, wsaNum);
+	_activeWSA[wsaNum].movie->close();
+}
+
 void KyraEngine_v2::seq_unloadWSA(int wsaNum) {
-	debugC(9, kDebugLevelMain, "KyraEngine_v2::seq_unloadWSA(%i)", wsaNum);
-	
 	if (_activeWSA[wsaNum].movie) {
 		_activeWSA[wsaNum].movie->close();
 		delete _activeWSA[wsaNum].movie;
@@ -591,5 +1182,166 @@
 	}
 }
 
+bool KyraEngine_v2::seq_processNextSubFrame(int wsaNum) {
+	uint32 currentFrame = _activeWSA[wsaNum].currentFrame;
+	uint32 currentTime = _system->getMillis();
+	
+	if (_activeWSA[wsaNum].callback && currentFrame != _activeWSA[wsaNum].lastFrame) {
+		_activeWSA[wsaNum].lastFrame = currentFrame;
+		currentFrame = (this->*_activeWSA[wsaNum].callback)(_activeWSA[wsaNum].movie, _activeWSA[wsaNum].x, _activeWSA[wsaNum].y, currentFrame);		
+	}
+
+	if (_activeWSA[wsaNum].movie) {
+		_activeWSA[wsaNum].movie->setDrawPage(2);
+		_activeWSA[wsaNum].movie->setX(_activeWSA[wsaNum].x);
+		_activeWSA[wsaNum].movie->setY(_activeWSA[wsaNum].y);
+		
+		if (_activeWSA[wsaNum].flags & 0x20) {
+			_activeWSA[wsaNum].movie->displayFrame(_activeWSA[wsaNum].control[currentFrame].frameIndex, 0x4000);
+			_activeWSA[wsaNum].frameDelay = _activeWSA[wsaNum].control[currentFrame].frameDelay;
+		} else {
+			_activeWSA[wsaNum].movie->displayFrame(currentFrame % _activeWSA[wsaNum].movie->frames(), 0x4000);
+		}
+	}
+
+	if (_activeWSA[wsaNum].flags & 0x10) {
+		currentFrame = (currentTime - _activeWSA[wsaNum].nextFrame) / (_activeWSA[wsaNum].frameDelay * _tickLength);
+	} else {
+		if (((int32)(currentTime - _activeWSA[wsaNum].nextFrame) / (int32)(_activeWSA[wsaNum].frameDelay * _tickLength)) > 0) {
+			currentFrame++;
+			_activeWSA[wsaNum].nextFrame += (_activeWSA[wsaNum].frameDelay * _tickLength);
+		}
+	}
+	
+	bool res = false;
+
+	if (currentFrame >= _activeWSA[wsaNum].endFrame) {
+		int sw = ((_activeWSA[wsaNum].flags & 0x1e) - 2);
+		switch (sw) {
+			case 0:
+				res = true;
+				currentFrame = _activeWSA[wsaNum].endFrame;
+				_screen->copyRegionToBuffer(2, 0, 0, 320, 200, _pageBuffer2);
+				break;
+
+			case 6:
+			case 8:
+				currentFrame = _activeWSA[wsaNum].endFrame - 1;
+				break;
+
+			case 2:
+			case 10:
+				currentFrame = _activeWSA[wsaNum].startFrame;
+				break;
+
+			default:
+				currentFrame = _activeWSA[wsaNum].endFrame - 1;
+				res = true;
+				break;
+		}
+	}
+
+	_activeWSA[wsaNum].currentFrame = currentFrame & 0xffff;
+	return res;
+}
+
+void KyraEngine_v2::seq_init() {
+	_pageBuffer1 = new uint8[64000];
+	_pageBuffer2 = new uint8[64000];
+	_seqProcessedString = new char[200];
+	_seqWsa = new WSAMovieV2(this);
+	_activeWSA = new ActiveWSA[8];
+	_activeText = new ActiveText[10];
+}
+
+void KyraEngine_v2::seq_uninit() {
+	delete [] _pageBuffer1;
+	_pageBuffer1 = NULL;
+	
+	delete [] _pageBuffer2;
+	_pageBuffer2 = NULL;
+
+	delete [] _seqProcessedString;
+	_seqProcessedString = NULL;
+	
+	delete [] _activeWSA;
+	_activeWSA = NULL;
+	
+	delete [] _activeText;
+	_activeText = NULL;
+	
+	delete _seqWsa;
+	_seqWsa = NULL;
+}
+
+// static res
+// TODO: move to staticres.cpp
+
+const Sequence KyraEngine_v2::_sequences[] = {
+	// flags, wsaFile, cpsFile, startupCommand, finalCommand, stringIndex1, stringIndex2,
+	// startFrame, numFrames, frameDelay, xPos, yPos, callback, duration
+	{ 2, 0, "virgin.cps",   4, 0, -1, -1, 0, 1,  100,  0, 0, 0,                                 30 },
+	{ 1, "westwood.wsa", 0, 4, 0, -1, -1, 0, 18, 12,   0, 0, &KyraEngine_v2::seq_introWestwood, 10 },
+	{ 1, "title.wsa", 0,    4, 0, -1, -1, 0, 26, 12,   0, 0, &KyraEngine_v2::seq_introTitle,    10 },
+	{ 2, 0, "over.cps",     4, 0, -1, -1, 0, 1,  3600, 0, 0, &KyraEngine_v2::seq_introOverview, 30 },
+	{ 2, 0, "library.cps",  4, 0, -1, -1, 0, 1,  3600, 0, 0, &KyraEngine_v2::seq_introLibrary,  30 },
+	{ 2, 0, "hand.cps",     4, 0, -1, -1, 0, 1,  3600, 0, 0, &KyraEngine_v2::seq_introHand,     90 },
+	{ 1, "point.wsa", 0,    4, 8, -1, -1, 0, 38, 7,    0, 0, &KyraEngine_v2::seq_introPoint,    200 },
+	{ 1, "zanfaun.wsa", 0,  4, 0, -1, -1, 0, 51, 16,   0, 0, &KyraEngine_v2::seq_introZanfaun,  240 },
+};
+
+const NestedSequence KyraEngine_v2::_nSequences[] = {
+	// flags, wsaFile, startframe, endFrame, frameDelay, callback, x, y, wsaControl, startupCommand, finalCommand, unk1;
+	{ 0x0C, "figgle.wsa",  0, 3,   60, /*&KyraEngine_v2::seq_finaleFiggle*/0, 0, 0, 0,              0, 0, 0 },
+
+	{ 8,    "over1.wsa",   0, 10,  10, &KyraEngine_v2::seq_introOver1,    0, 0, 0,                  0, 0, 0 },
+	{ 8,    "over2.wsa",   0, 11,  9,  &KyraEngine_v2::seq_introOver2,    0, 0, 0,                  0, 0, 0 },
+	{ 8,    "forest.wsa",  0, 22,  6,  &KyraEngine_v2::seq_introForest,   0, 0, 0,                  1, 3, 0 },
+	{ 8,    "dragon.wsa",  0, 11,  6,  &KyraEngine_v2::seq_introDragon,   0, 0, 0,                  2, 0, 0 },
+	{ 2,    "darm.wsa",    0, 19,  9,  &KyraEngine_v2::seq_introDarm,     0, 0, 0,                  4, 0, 0 },
+	{ 2,    "library.wsa", 0, 33,  9,  &KyraEngine_v2::seq_introLibrary2, 0, 0, 0,                  4, 0, 0 },
+	{ 0x2A, "library.wsa", 0, 18,  9,  &KyraEngine_v2::seq_introLibrary2, 0, 0, _wsaControlLibrary, 0, 0, 0 },
+	{ 0x0A, "marco.wsa",   0, 37,  9,  &KyraEngine_v2::seq_introMarco,    0, 0, 0,                  4, 0, 0 },
+	{ 2,    "hand1a.wsa",  0, 34,  9,  &KyraEngine_v2::seq_introHand1a,   0, 0, 0,                  0, 0, 0 },
+	{ 0x2A, "hand1b.wsa",  0, 16,  9,  &KyraEngine_v2::seq_introHand1b,   0, 0, _wsaControlHand1b,  0, 0, 0 },
+	{ 0x2A, "hand1c.wsa",  0, 9,   9,  &KyraEngine_v2::seq_introHand1c,   0, 0, _wsaControlHand1c,  0, 0, 0 },
+	{ 0x2C, "hand2.wsa",   0, 2,   9,  &KyraEngine_v2::seq_introHand2,    0, 0, _wsaControlHand2,   5, 0, 0 },
+	{ 0x2C, "hand3.wsa",   0, 4,   9,  &KyraEngine_v2::seq_introHand3,    0, 0, _wsaControlHand3,   5, 0, 0 },
+	{ 0x2C, "hand4.wsa",   0, 8,   9,  0,                                 0, 0, _wsaControlHand4,   5, 0, 0 }
+};
+
+
+const SequenceControl KyraEngine_v2::_wsaControlLibrary[] = {
+	{0x00, 0x0A}, {0x01, 0x0A}, {0x02, 0x0A}, {0x03, 0x0A}, {0x04, 0x0A}, {0x05, 0x0A},
+	{0x06, 0x0A}, {0x07, 0x0A}, {0x08, 0x0A}, {0x09, 0x0A}, {0x08, 0x0A}, {0x07, 0x0A},
+	{0x06, 0x0A}, {0x05, 0x28}, {0x04, 0x0A}, {0x03, 0x0A}, {0x02, 0x0A}, {0x01, 0x0A}
+};
+
+const SequenceControl KyraEngine_v2::_wsaControlHand1b[] = {
+	{0x00, 0x06}, {0x01, 0x06}, {0x02, 0x06}, {0x03, 0x06}, {0x04, 0x06}, {0x05, 0x06},
+	{0x06, 0x06}, {0x07, 0x06}, {0x08, 0x06}, {0x09, 0x06}, {0x0A, 0x06}, {0x0B, 0x06},
+	{0x0B, 0x0C}, {0x0C, 0x0C}, {0x0D, 0x0C}, {0x0C, 0x0C}, {0x0B, 0x0C}
+};
+
+const SequenceControl KyraEngine_v2::_wsaControlHand1c[] = {
+	{0x00, 0x06}, {0x01, 0x06}, {0x02, 0x06}, {0x03, 0x06}, {0x04, 0x06}, {0x03, 0x06},
+	{0x04, 0x06}, {0x05, 0x40}, {0x05, 0x06}
+};
+ 
+const SequenceControl KyraEngine_v2::_wsaControlHand2[] = {
+	{0x00, 0x06}, {0x01, 0x06}, {0x00, 0x06}, {0x01, 0x06}, {0x00, 0x06}, {0x01, 0x06},
+	{0x00, 0x06}, {0x01, 0x06}, {0x00, 0x06}, {0x01, 0x06}, {0x00, 0x06}, {0x01, 0x06},
+	{0x00, 0x06}, {0x01, 0x06}, {0x00, 0x06}, {0x01, 0x06}	
+};
+
+const SequenceControl KyraEngine_v2::_wsaControlHand3[] = {
+	{0x00, 0x06}, {0x01, 0x06}, {0x02, 0x06}, {0x01, 0x06}, {0x00, 0x01}
+};
+
+const SequenceControl KyraEngine_v2::_wsaControlHand4[] = {
+	{0x00, 0x06}, {0x01, 0x06}, {0x02, 0x06}, {0x03, 0x06}, {0x04, 0x06},
+	{0x03, 0x06}, {0x02, 0x06}, {0x01, 0x06}
+};
+
 } // end of namespace Kyra
 

Modified: scummvm/trunk/engines/kyra/staticres.cpp
===================================================================
--- scummvm/trunk/engines/kyra/staticres.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/staticres.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -1154,7 +1154,7 @@
 
 // kyra 2 static res
 
-const char *KyraEngine_v2::_introStrings[] = {
+const char *KyraEngine_v2::_sequenceStrings[] = {
 	"Kyrandia is disappearing!",
 	"Rock by rock...",
 	"...and tree by tree.",
@@ -1175,12 +1175,98 @@
 	" DUMMY STRING... ",
 	"If they think I'm going to walk all the way down there, they're nuts!",
 	" DUMMY STRING... ",
-	"Hurry up faun!"
+	" DUMMY STRING... ",
+	"Hurry up Faun!",
+
+	"Boy, that was a close call!",
+	"You said it pal. I, for one, am never going hunting again!",
+	"Ribbit.",
+	"How many times do I have to tell you? You're a toad.",
+	"Oh no! We're out of cheese!",
+	"Let's try this earwax. It's orange.",
+	"Mommy, when do I get the ivy?",
+	"Get out of here, shoo!",
+	"You cut, and I'll choose.",
+	"No. You cut and I'll choose.",
+	"I still say it was derivative drivel.",
+	"Aw, you still wouldn't recognize iambic pentameter if it bit you on the butt!",
+
+	"Executive Producer",
+	"Brett W. Sperry",
+	"Designed & Directed by",
+	"Rick Gush",
+	"Lead Programmer",
+	"Michael Legg",
+	"Art Management",
+	"Louis Castle",
+	"Joseph B. Hewitt IV",
+	"Lead Artist",
+	"Rick Parks",
+	"Additional Coding by",
+	"Philip W. Gorrow",
+	"Matt Collins",
+	"Mark McCubbin",
+	"Artists",
+	"Cameron Chun",
+	"Cary Averett",
+	"Cindy Chinn",
+	"Elie Arabian",
+	"Fei Cheng",
+	"Ferby Miguel",
+	"Frank Mendeola",
+	"Jack Martin",
+	"Jerry Moore",
+	"",
+	"Judith Peterson",
+	"Larry Miller",
+	"Lenny Lee",
+	"Louise Sandoval",
+	"Ren Olsen",
+	"Music & Sounds by",
+	"Paul Mudra",
+	"Frank Klepacki",
+	"Dwight Okahara",
+	"Pat Collins",
+	"Qualilty Assurance by",
+	"Glenn Sperry",
+	"Michael Lightner",
+	"William Foster",
+	"Jesse Clemit",
+	"Jeff Fillhaber",
+	"Manual, Package Design",
+	"& Fulfillment",
+	"Eydie Laramore",
+	"Lisa Marcinko",
+	"Lauren Rifkin",
+	"Congratulations!",
+	"Thank you for playing The Hand of Fate!",
+	"Guest Coding",
+	"Producer Liaison",
+	"Scott Duckett",
+	"Irvine Testers",
+	"Chris McFarland",
+	"Paul Moore",
+	"Chad Soares",
+	"Jared Brinkley",
+	"Jon Willliams",
+	"Chris Toft",
+	"Chris's Hair by",
+	"Cumulo Nimbus",
+	"Load a game",
+	"Introduction",
+	"Start a new game",
+	"Exit the game",
+	"Special Thanks to",
+	"Sake Joe Bostic-san",
+	"Tim Fritz",
+	"Kenny Dunne",
+	"Yukio Sekiguchi (Japan)",
+	"Takeshi Abo (Japan)"
 };
 
-const int KyraEngine_v2::_introStringsSize = ARRAYSIZE(KyraEngine_v2::_introStrings);
+const int KyraEngine_v2::_sequenceStringsSize = ARRAYSIZE(KyraEngine_v2::_sequenceStrings);
 
-const char *KyraEngine_v2::_introSoundList[] = {
+const char *KyraEngine_v2::_sequenceSoundListPC[] = {
 	"eintro1",
 	"eintro2",
 	"eintro3",
@@ -1198,6 +1284,7 @@
 	"0000130",
 	"0000180",
 	"0000160",
+
 	"asong",
 	"crowcaw",
 	"eyerub2",
@@ -1208,7 +1295,7 @@
 	"lambmom3",
 	"lambkid1",
 	"thunder2",
-	"tunder3",
+	"thunder3",
 	"wind6",
 	"h2odrop2",
 	"gasleak",
@@ -1230,8 +1317,10 @@
 	"theend"
 };
 
-const int KyraEngine_v2::_introSoundListSize = ARRAYSIZE(KyraEngine_v2::_introSoundList);
+const int KyraEngine_v2::_sequenceSoundListPCSize = ARRAYSIZE(KyraEngine_v2::_sequenceSoundListPC);
 
+const uint8 KyraEngine_v2::_seqTextColorPresets[] = { 0x01, 0x01, 0x00, 0x3f, 0x3f, 0x3f };
+
 const char *KyraEngine_v2::_languageExtension[] = {
 	"ENG",
 	"FRE",
@@ -1395,3 +1484,4 @@
 
 } // End of namespace Kyra
 
+

Modified: scummvm/trunk/engines/kyra/wsamovie.cpp
===================================================================
--- scummvm/trunk/engines/kyra/wsamovie.cpp	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/wsamovie.cpp	2007-10-19 22:16:00 UTC (rev 29233)
@@ -398,6 +398,13 @@
 	_frameOffsTable = new uint32[_numFrames + 2];
 	_frameOffsTable[0] = 0;
 	uint32 frameDataOffs = READ_LE_UINT32(wsaData); wsaData += 4;
+	bool firstFrame = true;
+	if (frameDataOffs == 0) {
+		firstFrame = false;
+		frameDataOffs = READ_LE_UINT32(wsaData);
+		_flags |= WF_NO_FIRST_FRAME;
+	}
+
 	for (int i = 1; i < _numFrames + 2; ++i) {
 		_frameOffsTable[i] = READ_LE_UINT32(wsaData) - frameDataOffs;
 		wsaData += 4;
@@ -412,7 +419,8 @@
 	memcpy(_frameData, wsaData, frameDataSize);
 
 	// decode first frame
-	Screen::decodeFrame4(_frameData, _deltaBuffer, _deltaBufferSize);
+	if (firstFrame)
+		Screen::decodeFrame4(_frameData, _deltaBuffer, _deltaBufferSize);
 
 	delete [] p;
 	_opened = true;
@@ -483,11 +491,11 @@
 	if (_flags & WF_OFFSCREEN_DECODE) {
 		if (_oldOff) {
 			// Kyrandia 1 offscreen buffer -> screen copy method of Kyrandia 1, needs to be present
-			// for our intro code that doesn't supply all the needed parameters for the Kyrandia 2 method
+			// for our Kyrandia 3 menu code
 			_vm->screen()->copyBlockToPage(_drawPage, _x, _y, _width, _height, _offscreenBuffer);
 		} else {
 			// This is the offscreen buffer -> screen copy method of Kyrandia 2 as it's implemented
-			// in the original, we use this in game
+			// in the original
 			Screen_v2 *screen = _vm->screen_v2();
 			int pageBackUp = screen->_curPage;
 			screen->_curPage = _drawPage;
@@ -512,3 +520,4 @@
 
 } // end of namespace Kyra
 
+

Modified: scummvm/trunk/engines/kyra/wsamovie.h
===================================================================
--- scummvm/trunk/engines/kyra/wsamovie.h	2007-10-19 21:26:35 UTC (rev 29232)
+++ scummvm/trunk/engines/kyra/wsamovie.h	2007-10-19 22:16:00 UTC (rev 29233)
@@ -125,6 +125,9 @@
 	
 	int width() const { return _width; }
 	int height() const { return _height; }
+
+	void setWidth(int w) { _width = w; }
+	void setHeight(int h) { _height = h; }
 	
 	// HACK for our intro code
 	void flagOldOff(bool enabled) { _oldOff = enabled; }
@@ -140,3 +143,4 @@
 
 #endif
 
+


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