[Scummvm-cvs-logs] CVS: scummvm/sword1 credits.cpp,NONE,1.1 credits.h,NONE,1.1 animation.cpp,1.27,1.28 animation.h,1.13,1.14 logic.cpp,1.43,1.44 sword1.cpp,1.67,1.68 sword1.h,1.20,1.21

Robert Göffringmann lavosspawn at users.sourceforge.net
Sat Dec 4 18:53:03 CET 2004


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

Modified Files:
	animation.cpp animation.h logic.cpp sword1.cpp sword1.h 
Added Files:
	credits.cpp credits.h 
Log Message:
added support for an international BS1 cutscene pack (which we didn't release yet)

--- NEW FILE: credits.cpp ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sword1/credits.cpp,v 1.1 2004/12/05 02:52:41 lavosspawn Exp $
 *
 */

#include "stdafx.h"
#include "credits.h"
#include "screen.h"
#include "common/file.h"
#include "sound/mixer.h"
#include "common/util.h"
#include "sound/audiostream.h"

#include "sword1.h"

#define CREDITS_X 480
#define CREDITS_Y 300
#define BUFSIZE_Y 640

#define START_X ((640 - CREDITS_X) / 2)
#define START_Y ((480 - CREDITS_Y) / 2)

#define SCROLL_TIMING (2000 / 59) // 29.5 frames per second

#define LOGO_FADEUP_TIME (133 * 1000)
#define LOGO_FADEDOWN_TIME (163 * 1000)

namespace Sword1 {

enum {
	FONT_PAL = 0,
	FONT,
	TEXT,
	REVO_PAL,
	REVO_LOGO,
	F_EOF
};

enum {
	FNT_LFT = 0,   // left column
	FNT_RGT,	   // right column
	FNT_CEN,	   // centered
	FNT_BIG = 64,  // big font
	FNT_EOL = 128, // linebreak
	FNT_EOB = 255  // end of textblock
};


CreditsPlayer::CreditsPlayer(OSystem *pSystem, SoundMixer *pMixer) {
	_system = pSystem;
	_mixer = pMixer;
	_smlFont = _bigFont = NULL;
}

bool spaceInBuf(uint16 blitSta, uint16 blitEnd, uint16 renderDest) {
	if (blitEnd > blitSta) {
		if ((renderDest > blitEnd) || (renderDest + 15 < blitSta))
			return true;
	} else {
		if ((renderDest > blitEnd) && (renderDest + 15 < blitSta))
			return true;
	}
	return false;
}

void CreditsPlayer::play(void) {
	AudioStream *bgSoundStream = AudioStream::openStreamFile("credits");
	if (bgSoundStream == NULL) {
		warning("\"credits.ogg\" not found, skipping credits sequence");
		return;
	}
	ArcFile credFile;
	if (!credFile.open("credits.dat")) {
		warning("\"credits.dat\" not found, skipping credits sequence");
		return;
	}

	uint8 *palSrc = credFile.fetchFile(FONT_PAL, &_palLen);
	for (uint32 cnt = 0; cnt < _palLen; cnt++)
		_palette[(cnt / 3) * 4 + cnt % 3] = palSrc[cnt];
	_palLen /= 3;	
    
	generateFonts(&credFile);

	uint8 *textData = credFile.fetchFile(TEXT);
	textData += READ_LE_UINT32(textData + SwordEngine::_systemVars.language * 4);

	uint8 *screenBuf = (uint8*)malloc(CREDITS_X * BUFSIZE_Y);
	memset(screenBuf, 0, CREDITS_X * BUFSIZE_Y);
	_system->copyRectToScreen(screenBuf, 640, 0, 0, 640, 480);
	_system->setPalette(_palette, 0, _palLen);
	_system->updateScreen();

	// everything's initialized, time to render and show the credits.
	PlayingSoundHandle bgSound;
	_mixer->playInputStream(&bgSound, bgSoundStream, true, 0);

	int relDelay = 0;
	uint16 scrollY = 0;
	uint16 renderY = BUFSIZE_Y / 2;
	uint16 clearY = 0xFFFF;
	bool clearLine = false;
	while (((*textData != FNT_EOB) || (scrollY != renderY)) && !SwordEngine::_systemVars.engineQuit) {
		if ((int32)_mixer->getSoundElapsedTime(bgSound) - relDelay < (SCROLL_TIMING * 2)) { // sync to audio
			if (scrollY < BUFSIZE_Y - CREDITS_Y)
				_system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, CREDITS_Y);
			else {
				_system->copyRectToScreen(screenBuf + scrollY * CREDITS_X, CREDITS_X, START_X, START_Y, CREDITS_X, BUFSIZE_Y - scrollY);
				_system->copyRectToScreen(screenBuf, CREDITS_X, START_X, START_Y + BUFSIZE_Y - scrollY, CREDITS_X, CREDITS_Y - (BUFSIZE_Y - scrollY));
			}
			_system->updateScreen();
		} else
			warning("frame skipped");

		while (spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, renderY) && (*textData != FNT_EOB)) {
			if (*textData & FNT_EOL) {
				renderY = (renderY + 16) % BUFSIZE_Y; // linebreak
				clearLine = true;
				*textData &= ~FNT_EOL;
			}
			if (spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, renderY)) {
				if (clearLine)
					memset(screenBuf + renderY * CREDITS_X, 0, 16 * CREDITS_X);
				clearLine = false;
				renderLine(screenBuf, textData + 1, renderY, *textData);
				if (*textData & FNT_BIG)
					renderY += 16;
				while (*++textData != 0) // search for the start of next string
					;
				textData++;
			}
			if (*textData == FNT_EOB)
				clearY = renderY;
		}
		if ((*textData == FNT_EOB) && spaceInBuf(scrollY, (scrollY + CREDITS_Y) % BUFSIZE_Y, clearY)) {
			memset(screenBuf + clearY * CREDITS_X, 0, 16 * CREDITS_X);
			clearY = (clearY + 16) % BUFSIZE_Y;
		}

		relDelay += SCROLL_TIMING;
		delay(relDelay - (int32)_mixer->getSoundElapsedTime(bgSound));
		scrollY = (scrollY + 1) % BUFSIZE_Y;
	}
	free(_smlFont);
	free(_bigFont);
	_smlFont = _bigFont = NULL;
	free(screenBuf);
	
	// credits done, now show the revolution logo
	uint8 *revoBuf = credFile.decompressFile(REVO_LOGO);
	uint8 *revoPal = credFile.fetchFile(REVO_PAL, &_palLen);
	_palLen /= 3;
	while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEUP_TIME) && !SwordEngine::_systemVars.engineQuit) {
		_system->updateScreen();
		delay(100);
	}
	memset(_palette, 0, 256 * 4);
	_system->setPalette(_palette, 0, 256);
	_system->copyRectToScreen(revoBuf, 480, START_X, START_Y, CREDITS_X, CREDITS_Y);
	_system->updateScreen();

	fadePalette(revoPal, true, _palLen);
	while ((_mixer->getSoundElapsedTime(bgSound) < LOGO_FADEDOWN_TIME) && !SwordEngine::_systemVars.engineQuit) {
		_system->updateScreen();
		delay(100);
	}
	fadePalette(revoPal, false, _palLen);
	delay(3000);

	if (SwordEngine::_systemVars.engineQuit)
		_mixer->stopAll();
	free(revoBuf);
}

void CreditsPlayer::fadePalette(uint8 *srcPal, bool fadeup, uint16 len) {
	int8 fadeDir = fadeup ? 1 : -1;
	int fadeStart = fadeup ? 0 : 12;

	int relDelay = _system->getMillis();
	for (int fadeStep = fadeStart; (fadeStep >= 0) && (fadeStep <= 12) && !SwordEngine::_systemVars.engineQuit; fadeStep += fadeDir) {
		for (uint16 cnt = 0; cnt < len * 3; cnt++)
			_palette[(cnt / 3) * 4 + (cnt % 3)] = (srcPal[cnt] * fadeStep) / 12;
		_system->setPalette(_palette, 0, 256);
		_system->updateScreen();
		relDelay += 1000 / 12;
		delay(relDelay - _system->getMillis());
	}
}

void CreditsPlayer::renderLine(uint8 *screenBuf, uint8 *line, uint16 yBufPos, uint8 flags) {
	uint8 *font;
	uint16 fntSize = 16;
	if (flags & FNT_BIG) {
		font = _bigFont;
		fntSize = 32;
		flags &= ~FNT_BIG;
	} else 
		font = _smlFont;

	uint16 width = getWidth(font, line);
	uint16 xBufPos = (flags == FNT_CEN) ? (CREDITS_X - width) / 2 : ((flags == FNT_LFT) ? (234 - width) : 255);
	uint8 *bufDest = screenBuf + yBufPos * CREDITS_X + xBufPos;
	while (*line) {
		uint8 *chrSrc = font + _numChars + (*line - 1) * fntSize * fntSize;
		for (uint16 cnty = 0; cnty < fntSize; cnty++) {
			for (uint16 cntx = 0; cntx < fntSize; cntx++)
				bufDest[cnty * CREDITS_X + cntx] = chrSrc[cntx];
			chrSrc += fntSize;
		}
		bufDest += font[*line++ - 1];
	}
}

uint16 CreditsPlayer::getWidth(uint8 *font, uint8 *line) {
	uint16 width = 0;
	while (*line)
		width += font[*line++ - 1];
	return width;
}

void CreditsPlayer::generateFonts(ArcFile *arcFile) {
	_bigFont = arcFile->decompressFile(FONT);
	_numChars = *_bigFont;
	memmove(_bigFont, _bigFont + 1, _numChars * (32 * 32 + 1));
	_smlFont = (uint8*)malloc(_numChars * (32 * 32 + 1));
	uint8 *src = _bigFont + _numChars;
	uint8 *dst = _smlFont + _numChars;
	for (uint16 cnt = 0; cnt < _numChars; cnt++) {
		_smlFont[cnt] = (_bigFont[cnt]++ + 1) / 2; // width table
		for (uint16 cnty = 0; cnty < 16; cnty++) {
			for (uint16 cntx = 0; cntx < 16; cntx++) {
				uint8 resR = (uint8)((_palette[src[0] * 4 + 0] + _palette[src[1] * 4 + 0] + _palette[src[32] * 4 + 0] + _palette[src[33] * 4 + 0]) >> 2);
				uint8 resG = (uint8)((_palette[src[0] * 4 + 1] + _palette[src[1] * 4 + 1] + _palette[src[32] * 4 + 1] + _palette[src[33] * 4 + 1]) >> 2);
				uint8 resB = (uint8)((_palette[src[0] * 4 + 2] + _palette[src[1] * 4 + 2] + _palette[src[32] * 4 + 2] + _palette[src[33] * 4 + 2]) >> 2);
				*dst++ = getPalIdx(resR, resG, resB);
				src += 2;
			}
			src += 32;
		}
	}
}

uint8 CreditsPlayer::getPalIdx(uint8 r, uint8 g, uint8 b) {
	for (uint16 cnt = 0; cnt < _palLen; cnt++)
		if ((_palette[cnt * 4 + 0] == r) && (_palette[cnt * 4 + 1] == g) && (_palette[cnt * 4 + 2] == b))
			return (uint8)cnt;
	assert(_palLen < 256);
	_palette[_palLen * 4 + 0] = r;
	_palette[_palLen * 4 + 1] = g;
	_palette[_palLen * 4 + 2] = b;
	return (uint8)_palLen++;
}

void CreditsPlayer::delay(int msecs) {

	OSystem::Event event;
	uint32 start = _system->getMillis();
	do {
		while (_system->pollEvent(event)) {
			switch (event.event_code) {
			case OSystem::EVENT_QUIT:
				SwordEngine::_systemVars.engineQuit = true;
				break;
			default:
				break;
			}
		}
		if (msecs > 0)
			_system->delayMillis(10);
	} while ((_system->getMillis() < start + msecs) && !SwordEngine::_systemVars.engineQuit);
}

ArcFile::ArcFile(void) {
	_buf = NULL;
}

ArcFile::~ArcFile(void) {
	if (_buf)
		free(_buf);
}

bool ArcFile::open(const char *name) {
	File arc;
	if (!arc.open(name))
		return false;
	_bufPos = _buf = (uint8*)malloc(arc.size());
	arc.read(_buf, arc.size());
	arc.close();
	return true;
}

void ArcFile::enterPath(uint32 id) {
	_bufPos += READ_LE_UINT32(_bufPos + id * 4);
}

uint8 *ArcFile::fetchFile(uint32 fileId, uint32 *size) {
	if (size)
		*size = READ_LE_UINT32(_bufPos + (fileId + 1) * 4) - READ_LE_UINT32(_bufPos + fileId * 4);
	return _bufPos + READ_LE_UINT32(_bufPos + fileId * 4);
}

uint8 *ArcFile::decompressFile(uint32 fileId) {
	uint32 size;
	uint8 *srcBuf = fetchFile(fileId, &size);
	uint8 *dstBuf = (uint8*)malloc(READ_LE_UINT32(srcBuf));
	uint8 *srcPos = srcBuf + 4;
	uint8 *dstPos = dstBuf;
	while (srcPos < srcBuf + size) {
		uint16 len = READ_LE_UINT16(srcPos);
		memset(dstPos, 0, len);
		dstPos += len;
		srcPos += 2;
		if (srcPos < srcBuf + size) {
			uint8 len = *srcPos++;
			memcpy(dstPos, srcPos, len);
			dstPos += len;
			srcPos += len;
		}
	}
	return dstBuf;
}

}; // end of namespace Sword1

--- NEW FILE: credits.h ---
/* ScummVM - Scumm Interpreter
 * Copyright (C) 2003-2004 The ScummVM project
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /cvsroot/scummvm/scummvm/sword1/credits.h,v 1.1 2004/12/05 02:52:41 lavosspawn Exp $
 *
 */

#ifndef BS1CREDITS_H
#define BS1CREDITS_H

#include "common/util.h"
class SoundMixer;
class OSystem;

namespace Sword1 {

class ArcFile {
public:
	ArcFile(void);
	~ArcFile(void);
	bool open(const char *name);
	uint8 *fetchFile(uint32 fileId, uint32 *size = NULL);
	uint8 *decompressFile(uint32 fileId);
	void enterPath(uint32 id);
	void backToRoot(void) { _bufPos = _buf; };
private:
	uint8 *_bufPos;
	uint8 *_buf;
};

class CreditsPlayer {
public:
	CreditsPlayer(OSystem *pSystem, SoundMixer *pMixer);
	void play(void);
private:
	void generateFonts(ArcFile *arcFile);
	void renderLine(uint8 *screenBuf, uint8 *line, uint16 yBufPos, uint8 flags);
	void fadePalette(uint8 *srcPal, bool fadeup, uint16 len);
	void delay(int msecs);
	uint16 getWidth(uint8 *font, uint8 *line);
	uint8 getPalIdx(uint8 r, uint8 g, uint8 b);
	uint8 _palette[256 * 4];
	uint32 _palLen;
	uint8 _numChars;

	OSystem *_system;
	SoundMixer *_mixer;

	uint8 *_smlFont, *_bigFont;
};

}; // end of namespace Sword1

#endif // BS1CREDITS_H

Index: animation.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/animation.cpp,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- animation.cpp	28 Sep 2004 20:19:34 -0000	1.27
+++ animation.cpp	5 Dec 2004 02:52:41 -0000	1.28
@@ -21,12 +21,14 @@
 
 #include "common/stdafx.h"
 #include "common/file.h"
+#include "sword1/sword1.h"
 #include "sword1/animation.h"
-#include "sound/audiostream.h"
-
+#include "sword1/credits.h"
+#include "sound/vorbis.h"
 
 #include "common/config-manager.h"
 #include "common/str.h"
+
 namespace Sword1 {
 
 AnimationState::AnimationState(Screen *scr, SoundMixer *snd, OSystem *sys)
@@ -38,11 +40,9 @@
 
 
 #ifdef BACKEND_8BIT
-
 void AnimationState::setPalette(byte *pal) {
 	_sys->setPalette(pal, 0, 256);
 }
-
 #endif
 
 void AnimationState::drawYUV(int width, int height, byte *const *dat) {
@@ -50,28 +50,95 @@
 	_scr->plotYUV(lut, width, height, dat);
 #else
 	plotYUV(lookup, width, height, dat);
+#endif
+}
+
+void AnimationState::updateScreen(void) {
+#ifndef BACKEND_8BIT
 	_sys->copyRectToOverlay(overlay, MOVIE_WIDTH, 0, 40, MOVIE_WIDTH, MOVIE_HEIGHT);
 #endif
+	_sys->updateScreen();
+}
+
+OverlayColor *AnimationState::giveRgbBuffer(void) {
+#ifdef BACKEND_8BIT
+	return NULL;
+#else
+	return overlay;
+#endif
+}
+
+bool AnimationState::soundFinished(void) {
+	return !bgSound.isActive();
+}
+
+AudioStream *AnimationState::createAudioStream(const char *name, void *arg) {
+	if (arg)
+		return (AudioStream*)arg;
+	else
+		return AudioStream::openStreamFile(name);
 }
 
 MoviePlayer::MoviePlayer(Screen *scr, SoundMixer *snd, OSystem *sys)
 	: _scr(scr), _snd(snd), _sys(sys) {
+		for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++)
+			_logoOvls[cnt] = NULL;
+		_introPal = NULL;
+}
+
+MoviePlayer::~MoviePlayer(void) {
+	if (_introPal)
+		free(_introPal);
+	for (uint8 cnt = 0; cnt < INTRO_LOGO_OVLS; cnt++)
+		if (_logoOvls[cnt])
+			free(_logoOvls[cnt]);
 }
 
 /**
  * Plays an animated cutscene.
- * @param filename the file name of the cutscene file
+ * @param id the id of the file
  */
-void MoviePlayer::play(const char *filename) {
+void MoviePlayer::play(uint32 id) {
 #ifdef USE_MPEG2
 	AnimationState *anim = new AnimationState(_scr, _snd, _sys);
-	bool initOK = anim->init(filename);
+	AudioStream *stream = NULL;
+	if (SwordEngine::_systemVars.cutscenePackVersion == 1) {
+		if ((id == SEQ_INTRO) || (id == SEQ_FINALE) || (id == SEQ_HISTORY) || (id == SEQ_FERRARI)) {
+			// these sequences are language specific
+			char sndName[20];
+			sprintf(sndName, "%s.snd", _sequenceList[id]);
+			File *oggSource = new File();
+			if (oggSource->open(sndName)) {
+				SplittedAudioStream *sStream = new SplittedAudioStream();
+				uint32 numSegs = oggSource->readUint32LE(); // number of audio segments, either 1 or 2.
+				// for each segment and each of the 7 languages, we've got fileoffset and size
+				uint32 *header = (uint32*)malloc(numSegs * 7 * 2 * 4);
+				for (uint32 cnt = 0; cnt < numSegs * 7 * 2; cnt++)
+					header[cnt] = oggSource->readUint32LE();
+				for (uint32 segCnt = 0; segCnt < numSegs; segCnt++) {
+					oggSource->seek( header[SwordEngine::_systemVars.language * 2 + 0 + segCnt * 14]);
+					uint32 segSize = header[SwordEngine::_systemVars.language * 2 + 1 + segCnt * 14];
+					AudioStream *apStream = makeVorbisStream(oggSource, segSize);
+					if (!apStream)
+						error("Can't create Vorbis Stream from file %s", sndName);
+					sStream->appendStream(apStream);
+				}
+				free(header);
+				stream = sStream;
+			} else
+				warning("Sound file \"%s\" not found", sndName);
+			initOverlays(id);
+			oggSource->decRef();
+		}
+	}
+	bool initOK = anim->init(_sequenceList[id], stream);
 
+    uint32 frameCount = 0;
 	if (initOK) {
 		while (anim->decodeFrame()) {
-#ifndef BACKEND_8BIT
-			_sys->updateScreen();
-#endif
+			processFrame(id, anim, frameCount);
+			anim->updateScreen();
+			frameCount++;
 			OSystem::Event event;
 			while (_sys->pollEvent(event)) {
 				switch (event.event_code) {
@@ -95,10 +162,143 @@
 			}
 		}
 	}
-
+	while (!anim->soundFinished())
+		_sys->delayMillis(100);
 	delete anim;
+#endif // USE_MPEG2
+}
+
+void MoviePlayer::insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal) {
+	if (ovl != NULL)
+		for (uint32 cnt = 0; cnt < 640 * 400; cnt++)
+			if (ovl[cnt])
+				buf[cnt] = pal[ovl[cnt]];
+}
+
+void MoviePlayer::processFrame(uint32 animId, AnimationState *anim, uint32 frameNo) {
+#if defined(USE_MPEG2) && !defined(BACKEND_8BIT)
+	if ((animId != 4) || (SwordEngine::_systemVars.cutscenePackVersion == 0))
+		return;
+	OverlayColor *buf = anim->giveRgbBuffer();
+	if ((frameNo > 397) && (frameNo < 444)) { // Broken Sword Logo
+		if (frameNo <= 403)
+			insertOverlay(buf, _logoOvls[frameNo - 398], _introPal); // fade up
+		else if (frameNo <= 437)
+			insertOverlay(buf, _logoOvls[(frameNo - 404) % 6 + 6], _introPal); // animation
+		else {
+			insertOverlay(buf, _logoOvls[5 - (frameNo - 438)], _introPal); // fade down
+		}
+	}
+#endif
+}
 
+bool MoviePlayer::initOverlays(uint32 id) {
+#if defined(USE_MPEG2) && !defined(BACKEND_8BIT)
+	if (id == SEQ_INTRO) {
+		ArcFile ovlFile;
+		if (!ovlFile.open("intro.dat")) {
+			warning("\"intro.dat\" not found");
+			return false;
+		}
+		ovlFile.enterPath(SwordEngine::_systemVars.language);
+		for (uint8 fcnt = 0; fcnt < 12; fcnt++) {
+			_logoOvls[fcnt] = ovlFile.decompressFile(fcnt);
+			if (fcnt > 0)
+				for (uint32 cnt = 0; cnt < 640 * 400; cnt++)
+					if (_logoOvls[fcnt - 1][cnt] && !_logoOvls[fcnt][cnt])
+						_logoOvls[fcnt][cnt] = _logoOvls[fcnt - 1][cnt];
+		}
+		uint8 *pal = ovlFile.fetchFile(12);
+		_introPal = (OverlayColor*)malloc(256 * sizeof(OverlayColor));
+		for (uint16 cnt = 0; cnt < 256; cnt++)
+			_introPal[cnt] = _sys->RGBToColor(pal[cnt * 3 + 0], pal[cnt * 3 + 1], pal[cnt * 3 + 2]);
+	}
+	return true;
 #endif
 }
 
+SplittedAudioStream::SplittedAudioStream(void) {
+	_queue = NULL;
+}
+
+SplittedAudioStream::~SplittedAudioStream(void) {
+	while (_queue) {
+		delete _queue->stream;
+		FileQueue *que = _queue->next;
+		delete _queue;
+		_queue = que;
+	}
+}
+
+int SplittedAudioStream::getRate(void) const {
+	if (_queue)
+		return _queue->stream->getRate();
+	else
+		return 22050;
+}
+
+void SplittedAudioStream::appendStream(AudioStream *stream) {
+	FileQueue **que = &_queue;
+	while (*que)
+		que = &((*que)->next);
+	*que = new FileQueue;
+	(*que)->stream = stream;
+	(*que)->next = NULL;
+}
+
+bool SplittedAudioStream::endOfData(void) const {
+	if (_queue)
+		return _queue->stream->endOfData();
+	else
+		return true;
+}
+
+bool SplittedAudioStream::isStereo(void) const {
+	if (_queue)
+		return _queue->stream->isStereo();
+	else
+		return false; // all the BS1 files are mono, anyways.
+}
+
+int SplittedAudioStream::readBuffer(int16 *buffer, const int numSamples) {
+	int retVal = 0;
+	int needSamples = numSamples;
+	while (needSamples && _queue) {
+		int retSmp = _queue->stream->readBuffer(buffer, needSamples);
+		needSamples -= retSmp;
+		retVal += retSmp;
+		buffer += retSmp;
+		if (_queue->stream->endOfData()) {
+			delete _queue->stream;
+			FileQueue *que = _queue->next;
+			delete _queue;
+			_queue = que;
+		}
+	}
+	return retVal;
+}
+
+const char * MoviePlayer::_sequenceList[20] = {
+    "ferrari",  // 0  CD2   ferrari running down fitz in sc19
+    "ladder",   // 1  CD2   george walking down ladder to dig sc24->sc$
+    "steps",    // 2  CD2   george walking down steps sc23->sc24
+    "sewer",    // 3  CD1   george entering sewer sc2->sc6
+    "intro",    // 4  CD1   intro sequence ->sc1
+    "river",    // 5  CD1   george being thrown into river by flap & g$
+    "truck",    // 6  CD2   truck arriving at bull's head sc45->sc53/4
+    "grave",    // 7  BOTH  george's grave in scotland, from sc73 + from sc38 $
+    "montfcon", // 8  CD2   monfaucon clue in ireland dig, sc25
+    "tapestry", // 9  CD2   tapestry room beyond spain well, sc61
+    "ireland",  // 10 CD2   ireland establishing shot europe_map->sc19
+    "finale",   // 11 CD2   grand finale at very end, from sc73
+    "history",  // 12 CD1   George's history lesson from Nico, in sc10
+    "spanish",  // 13 CD2   establishing shot for 1st visit to Spain, europe_m$
+    "well",     // 14 CD2   first time being lowered down well in Spai$
+    "candle",   // 15 CD2   Candle burning down in Spain mausoleum sc59
+    "geodrop",  // 16 CD2   from sc54, George jumping down onto truck
+    "vulture",  // 17 CD2   from sc54, vultures circling George's dead body
+    "enddemo",  // 18 ---   for end of single CD demo
+    "credits",  // 19 CD2   credits, to follow "finale" sequence
+};
+
 } // End of namespace Sword1

Index: animation.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/animation.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- animation.h	23 Mar 2004 00:10:18 -0000	1.13
+++ animation.h	5 Dec 2004 02:52:41 -0000	1.14
@@ -26,10 +26,35 @@
 
 #include "sword1/screen.h"
 #include "sword1/sound.h"
+#include "sound/audiostream.h"
 
+namespace Sword1 {
 
+enum {
+	SEQ_FERRARI = 0,
+	SEQ_LADDER,
+	SEQ_STEPS,
+	SEQ_SEWER,
+	SEQ_INTRO,
+	SEQ_RIVER,
+	SEQ_TRUCK,
+	SEQ_GRAVE,
+	SEQ_MONTFCON,
+	SEQ_TAPESTRY,
+	SEQ_IRELAND,
+	SEQ_FINALE,
+	SEQ_HISTORY,
+	SEQ_SPANISH,
+	SEQ_WELL,
+	SEQ_CANDLE,
+	SEQ_GEODROP,
+	SEQ_VULTURE,
+	SEQ_ENDDEMO,
+	SEQ_CREDITS
+};
 
-namespace Sword1 {
+#define INTRO_LOGO_OVLS 12
+#define INTRO_TEXT_OVLS 8
 
 class AnimationState : public Graphics::BaseAnimationState {
 private:
@@ -38,6 +63,9 @@
 public:
 	AnimationState(Screen *scr, SoundMixer *snd, OSystem *sys);
 	~AnimationState();
+	void updateScreen();
+	OverlayColor *giveRgbBuffer(void);
+	bool soundFinished();
 
 private:
 	void drawYUV(int width, int height, byte *const *dat);
@@ -45,19 +73,48 @@
 #ifdef BACKEND_8BIT
 	void setPalette(byte *pal);
 #endif
+
+protected:
+	virtual AudioStream *createAudioStream(const char *name, void *arg);
 };
 
 class MoviePlayer {
+public:
+	MoviePlayer(Screen *scr, SoundMixer *snd, OSystem *sys);
+	~MoviePlayer(void);
+	void play(uint32 id);
 private:
+	void insertOverlay(OverlayColor *buf, uint8 *ovl, OverlayColor *pal);
+	void processFrame(uint32 animId, AnimationState *anim, uint32 frameNo);
+	bool initOverlays(uint32 id);
+	void decompressRle(uint8 *src, uint8 *dest, uint32 srcSize);
 	Screen *_scr;
 	SoundMixer *_snd;
 	OSystem *_sys;
 
+	static const char *_sequenceList[20];
+	uint8 *_logoOvls[INTRO_LOGO_OVLS];
+	OverlayColor *_introPal;
+};
+
+struct FileQueue {
+	AudioStream *stream;
+	FileQueue *next;
+};
+
+class SplittedAudioStream : public AudioStream {
 public:
-	MoviePlayer(Screen *scr, SoundMixer *snd, OSystem *sys);
-	void play(const char *filename);
+	SplittedAudioStream(void);
+	~SplittedAudioStream(void);
+	void appendStream(AudioStream *stream);
+	virtual int readBuffer(int16 *buffer, const int numSamples);
+	virtual bool isStereo(void) const;
+	virtual bool endOfData(void) const;
+	virtual int getRate(void) const;
+private:
+	FileQueue *_queue;
 };
 
-} // End of namespace Sword2
+} // End of namespace Sword1
 
 #endif

Index: logic.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/logic.cpp,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- logic.cpp	24 Nov 2004 21:03:20 -0000	1.43
+++ logic.cpp	5 Dec 2004 02:52:41 -0000	1.44
@@ -34,6 +34,7 @@
 #include "sword1/music.h"
 #include "sword1/swordres.h"
 #include "sword1/animation.h"
+#include "sword1/credits.h"
 
 #include "sword1/debug.h"
 
@@ -940,37 +941,13 @@
 
 int Logic::fnPlaySequence(Object *cpt, int32 id, int32 sequenceId, int32 d, int32 e, int32 f, int32 z, int32 x) {
 
-  static const char *sequence_list[20] = {
-    "ferrari",  // 0  CD2   ferrari running down fitz in sc19
-    "ladder",   // 1  CD2   george walking down ladder to dig sc24->sc$
-    "steps",    // 2  CD2   george walking down steps sc23->sc24
-    "sewer",    // 3  CD1   george entering sewer sc2->sc6
-    "intro",    // 4  CD1   intro sequence ->sc1
-    "river",    // 5  CD1   george being thrown into river by flap & g$
-    "truck",    // 6  CD2   truck arriving at bull's head sc45->sc53/4
-    "grave",    // 7  BOTH  george's grave in scotland, from sc73 + from sc38 $
-    "montfcon", // 8  CD2   monfaucon clue in ireland dig, sc25
-    "tapestry", // 9  CD2   tapestry room beyond spain well, sc61
-    "ireland",  // 10 CD2   ireland establishing shot europe_map->sc19
-    "finale",   // 11 CD2   grand finale at very end, from sc73
-    "history",  // 12 CD1   George's history lesson from Nico, in sc10
-    "spanish",  // 13 CD2   establishing shot for 1st visit to Spain, europe_m$
-    "well",     // 14 CD2   first time being lowered down well in Spai$
-    "candle",   // 15 CD2   Candle burning down in Spain mausoleum sc59
-    "geodrop",  // 16 CD2   from sc54, George jumping down onto truck
-    "vulture",  // 17 CD2   from sc54, vultures circling George's dead body
-    "enddemo",  // 18 ---   for end of single CD demo
-    "credits",  // 19 CD2   credits, to follow "finale" sequence
-    // etc.
-  };
-
-  MoviePlayer player(_screen, _mixer, _system);
-
-  player.play(sequence_list[sequenceId]);
-
-	//_scriptVars[NEW_PALETTE] = 1;
-	/* the logic usually calls fnFadeDown before playing the sequence, so we have to
-	   set NEW_PALETTE now to force a palette refresh */
+	if ((SwordEngine::_systemVars.cutscenePackVersion == 1) && (sequenceId == SEQ_CREDITS)) {
+		CreditsPlayer player(_system, _mixer);
+		player.play();
+	} else {
+		MoviePlayer player(_screen, _mixer, _system);
+		player.play(sequenceId);
+	}
 	return SCRIPT_CONT;
 }
 

Index: sword1.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/sword1.cpp,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -d -r1.67 -r1.68
--- sword1.cpp	29 Nov 2004 00:25:14 -0000	1.67
+++ sword1.cpp	5 Dec 2004 02:52:41 -0000	1.68
@@ -1134,6 +1134,15 @@
 			error(msg);
 		}
 	}
+
+	// check cutscene pack version
+	_systemVars.cutscenePackVersion = 0;
+#ifdef USE_MPEG2
+	if (test.open("intro.snd")) {
+		_systemVars.cutscenePackVersion = 1;
+		test.close();
+	}
+#endif
 }
 
 int SwordEngine::go() {

Index: sword1.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/sword1/sword1.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -d -r1.20 -r1.21
--- sword1.h	24 Nov 2004 00:14:20 -0000	1.20
+++ sword1.h	5 Dec 2004 02:52:41 -0000	1.21
@@ -63,6 +63,8 @@
 	uint8	showText;
 	uint8	language;
 	bool    isDemo;
+
+	uint8	cutscenePackVersion;
 };
 
 class SwordEngine : public Engine {





More information about the Scummvm-git-logs mailing list