[Scummvm-cvs-logs] SF.net SVN: scummvm: [25158] scummvm/trunk/engines/scumm

cyx at users.sourceforge.net cyx at users.sourceforge.net
Sun Jan 21 23:08:03 CET 2007


Revision: 25158
          http://scummvm.svn.sourceforge.net/scummvm/?rev=25158&view=rev
Author:   cyx
Date:     2007-01-21 14:08:02 -0800 (Sun, 21 Jan 2007)

Log Message:
-----------
added handler for sfx sync (abc-slideshow.cup, bda-slideshow.cup) and sfx looping, cleanup

Modified Paths:
--------------
    scummvm/trunk/engines/scumm/he/cup_player_he.cpp
    scummvm/trunk/engines/scumm/he/cup_player_he.h
    scummvm/trunk/engines/scumm/he/intern_he.h
    scummvm/trunk/engines/scumm/scumm.cpp

Modified: scummvm/trunk/engines/scumm/he/cup_player_he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/cup_player_he.cpp	2007-01-21 22:06:54 UTC (rev 25157)
+++ scummvm/trunk/engines/scumm/he/cup_player_he.cpp	2007-01-21 22:08:02 UTC (rev 25158)
@@ -30,6 +30,10 @@
 
 namespace Scumm {
 
+CUP_Player::CUP_Player(OSystem *sys, ScummEngine_vCUPhe *vm, Audio::Mixer *mixer)
+	: _vm(vm), _mixer(mixer), _system(sys) {
+}
+
 bool CUP_Player::open(const char *filename) {
 	bool opened = false;
 	debug(1, "opening '%s'", filename);
@@ -37,19 +41,34 @@
 		uint32 tag = _fd.readUint32BE();
 		_fd.readUint32BE();
 		if (tag == MKID_BE('BEAN')) {
-			_playbackRate = 66;
-			_width = 640;
-			_height = 480;
-			_offscreenBuffer = (uint8 *)malloc(_width * _height);
-			memset(_offscreenBuffer, 0, _width * _height);
+			_playbackRate = kDefaultPlaybackRate;
+			_width = kDefaultVideoWidth;
+			_height = kDefaultVideoHeight;
+
+			memset(_paletteData, 0, sizeof(_paletteData));
 			_paletteChanged = false;
+			_offscreenBuffer = 0;
+
+			_currentChunkData = 0;
+			_currentChunkSize = 0;
+			_bufferLzssData = 0;
+			_bufferLzssSize = 0;
+
 			_sfxCount = 0;
 			_sfxBuffer = 0;
-			_sfxHandleTable = 0;
+			for (int i = 0; i < kSfxChannels; ++i) {
+				_sfxChannels[i].sfxNum = -1;
+			}
 			memset(_sfxQueue, 0, sizeof(_sfxQueue));
 			_sfxQueuePos = 0;
+			_lastSfxChannel = -1;
+
 			parseHeaderTags();
 			debug(1, "rate %d width %d height %d", _playbackRate, _width, _height);
+
+			_offscreenBuffer = (uint8 *)malloc(_width * _height);
+			memset(_offscreenBuffer, 0, _width * _height);
+
 			opened = true;
 		}
 	}
@@ -59,8 +78,9 @@
 void CUP_Player::close() {
 	_fd.close();
 	free(_offscreenBuffer);
+	_offscreenBuffer = 0;
 	free(_sfxBuffer);
-	delete[] _sfxHandleTable;
+	_sfxBuffer = 0;
 }
 
 uint32 CUP_Player::loadNextChunk() {
@@ -106,13 +126,12 @@
 
 void CUP_Player::play() {
 	int ticks = _system->getMillis();
-	while (_currentChunkSize != 0 && !_vm->_quit) {
+	while (_currentChunkSize != 0 && !_vm->_quit && !_fd.ioFailed()) {
 		uint32 tag, size;
 		parseNextTag(_currentChunkData, tag, size);
 		if (tag == MKID_BE('BLOK')) {
-			bool fastMode = false;
 			int diff = _system->getMillis() - ticks;
-			if (diff >= 0 && diff <= _playbackRate && !fastMode) {
+			if (diff >= 0 && diff <= _playbackRate) {
 				_system->delayMillis(_playbackRate - diff);
 			} else {
 				_system->delayMillis(1);
@@ -145,36 +164,69 @@
 void CUP_Player::updateSfx() {
 	for (int i = 0; i < _sfxQueuePos; ++i) {
 		const CUP_Sfx *sfx = &_sfxQueue[i];
-		int index;
 		if (sfx->num == -1) {
-			for (index = 0; index < _sfxCount; ++index) {
-				if (_mixer->isSoundHandleActive(_sfxHandleTable[index])) {
+			debug(1, "Stopping sound channel %d", _lastSfxChannel);
+			if (_lastSfxChannel != -1) {
+				_mixer->stopHandle(_sfxChannels[_lastSfxChannel].handle);
+			}
+			continue;
+		}
+		if ((sfx->flags & kSfxFlagRestart) == 0) {
+			bool alreadyPlaying = false;
+			for (int ch = 0; ch < kSfxChannels; ++ch) {
+				if (_mixer->isSoundHandleActive(_sfxChannels[ch].handle) && _sfxChannels[ch].sfxNum == sfx->num) {
+					alreadyPlaying = true;
 					break;
 				}
 			}
-			if (index == _sfxCount) {
+			if (alreadyPlaying) {
 				continue;
 			}
-		} else {
-			index = sfx->num - 1;
 		}
-		assert(index >= 0 && index < _sfxCount);
-		if (!_mixer->isSoundHandleActive(_sfxHandleTable[index]) || (sfx->mode & 2) != 0) {
-			if ((sfx->flags & 0x8000) == 0) {
-				warning("Unhandled Sfx looping");
-				continue;
+		CUP_SfxChannel *sfxChannel = 0;
+		for (int ch = 0; ch < kSfxChannels; ++ch) {
+			if (!_mixer->isSoundHandleActive(_sfxChannels[ch].handle)) {
+				_lastSfxChannel = ch;
+				sfxChannel = &_sfxChannels[ch];
+				sfxChannel->sfxNum = sfx->num;
+				sfxChannel->flags = sfx->flags;
+				break;
 			}
-			uint32 offset = READ_LE_UINT32(_sfxBuffer + index * 4) - 8;
+		}
+		if (sfxChannel) {
+			debug(1, "Start sound %d channel %d flags 0x%X", sfx->num, _lastSfxChannel, sfx->flags);
+			int sfxIndex = sfxChannel->sfxNum - 1;
+			assert(sfxIndex >= 0 && sfxIndex < _sfxCount);
+			uint32 offset = READ_LE_UINT32(_sfxBuffer + sfxIndex * 4) - 8;
 			uint8 *soundData = _sfxBuffer + offset;
 			if (READ_BE_UINT32(soundData) == MKID_BE('DATA')) {
 				uint32 soundSize = READ_BE_UINT32(soundData + 4);
-				_mixer->playRaw(&_sfxHandleTable[index], soundData + 8, soundSize - 8, 11025, Audio::Mixer::FLAG_UNSIGNED);
+				uint32 flags = Audio::Mixer::FLAG_UNSIGNED;
+				uint32 loopEnd = 0;
+				if (sfx->flags & kSfxFlagLoop) {
+					flags |= Audio::Mixer::FLAG_LOOP;
+					loopEnd = soundSize - 8;
+				}
+				_mixer->playRaw(&sfxChannel->handle, soundData + 8, soundSize - 8, 11025, flags, -1, 255, 0, 0, loopEnd);
 			}
+		} else {
+			warning("Unable to find a free channel to play sound %d", sfx->num);
 		}
 	}
 	_sfxQueuePos = 0;
 }
 
+void CUP_Player::waitForSfxChannel(int channel) {
+	assert(channel >= 0 && channel < kSfxChannels);
+	CUP_SfxChannel *sfxChannel = &_sfxChannels[channel];
+	if ((sfxChannel->flags & kSfxFlagLoop) == 0) {
+		while (_mixer->isSoundHandleActive(sfxChannel->handle) && !_vm->_quit) {
+			_vm->parseEvents();
+			_system->delayMillis(10);
+		}
+	}
+}
+
 void CUP_Player::parseNextTag(const uint8 *data, uint32 &tag, uint32 &size) {
 	tag = READ_BE_UINT32(data);
 	size = READ_BE_UINT32(data + 4);
@@ -211,7 +263,7 @@
 	case MKID_BE('WRLE'):
 		// this is never triggered
 	default:
-		warning("unhandled tag %s", tag2str(tag));
+		warning("Unhandled tag %s", tag2str(tag));
 		break;
 	}
 }
@@ -232,21 +284,15 @@
 				if (_sfxBuffer) {
 					memcpy(_sfxBuffer, data + 8, dataSize - 16);
 				}
-				_sfxHandleTable = new Audio::SoundHandle[_sfxCount];
 			}
 		}
 	}
 }
 
 void CUP_Player::handleRGBS(const uint8 *data, uint32 dataSize) {
-	int i;
-	uint8 *ptr = _paletteData;
-
-	for (i = 0; i < 256; i++) {
-		*ptr++ = *data++;
-		*ptr++ = *data++;
-		*ptr++ = *data++;
-		*ptr++ = 0;
+	for (int i = 0; i < 256; i++) {
+		memcpy(&_paletteData[i * 4], data, 3);
+		data += 3;
 	}
 	_paletteChanged = true;
 }
@@ -378,20 +424,21 @@
 			data += 8;
 			uint32 offset1 = READ_LE_UINT32(data);
 			uint32 offset2 = READ_LE_UINT32(data + 4);
-			decodeLzssData(_bufferLzssData, data + 8, data + offset1, data + offset2, _tempLzssBuffer);
+			decodeLZSS(_bufferLzssData, data + 8, data + offset1, data + offset2);
 			return _bufferLzssData;
 		}
 	}
 	return 0;
 }
 
-void CUP_Player::decodeLzssData(uint8 *dst1, const uint8 *src1, const uint8 *src2, const uint8 *src3, uint8 *dst2) {
+void CUP_Player::decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const uint8 *src3) {
+	uint8 wnd[4096];
 	int index = 1;
 	while (1) {
 		int code = *src1++;
 		for (int b = 0; b < 8; ++b) {
 			if (code & (1 << b)) {
-				*dst1++ = dst2[index] = *src2++;
+				*dst++ = wnd[index] = *src2++;
 				++index;
 				index &= 0xFFF;
 			} else {
@@ -402,7 +449,7 @@
 					return;
 				}
 				while (count--) {
-					*dst1++ = dst2[index] = dst2[offs];
+					*dst++ = wnd[index] = wnd[offs];
 					++index;
 					index &= 0xFFF;
 					++offs;
@@ -419,14 +466,13 @@
 }
 
 void CUP_Player::handleSNDE(const uint8 *data, uint32 dataSize) {
-	if (_sfxQueuePos < ARRAYSIZE(_sfxQueue)) {
-		CUP_Sfx *sfx = &_sfxQueue[_sfxQueuePos];
-		sfx->mode = READ_LE_UINT32(data);
-		sfx->num = (int16)READ_LE_UINT16(data + 4);
-		// READ_LE_UINT16(data + 6); // unused
-		sfx->flags = READ_LE_UINT16(data + 8);
-		++_sfxQueuePos;
-	}
+	assert(_sfxQueuePos < kSfxQueueSize);
+	CUP_Sfx *sfx = &_sfxQueue[_sfxQueuePos];
+	sfx->flags = READ_LE_UINT32(data);
+	sfx->num = READ_LE_UINT16(data + 4);
+	uint16 loop = READ_LE_UINT16(data + 8);
+	assert((loop & 0x8000) != 0); // this is never triggered
+	++_sfxQueuePos;
 }
 
 void CUP_Player::handleTOIL(const uint8 *data, uint32 dataSize) {
@@ -443,18 +489,21 @@
 			}
 			switch (code) {
 			case 1:
+				for (int i = 0; i < kSfxChannels; ++i) {
+					waitForSfxChannel(i);
+				}
 				_vm->_quit = true;
 				break;
-			case 7: { // pause playback
-					int sfxSync = READ_LE_UINT32(data);
-					warning("Unhandled playback pause %d", sfxSync);
+			case 7: {
+					int channelSync = READ_LE_UINT32(data);
+					waitForSfxChannel(channelSync);
 				}
 				break;
 			case 2: // display copyright/information messagebox
 			case 3: // no-op in the original
 			case 4: // restart playback
 			case 5: // disable normal screen update
-			case 6: // perform offscreen buffers swapping
+			case 6: // enable double buffer rendering
 				// these are never triggered
 			default:
 				warning("Unhandled TOIL code=%d", code);

Modified: scummvm/trunk/engines/scumm/he/cup_player_he.h
===================================================================
--- scummvm/trunk/engines/scumm/he/cup_player_he.h	2007-01-21 22:06:54 UTC (rev 25157)
+++ scummvm/trunk/engines/scumm/he/cup_player_he.h	2007-01-21 22:08:02 UTC (rev 25158)
@@ -27,44 +27,34 @@
 namespace Scumm {
 
 struct CUP_Sfx {
-	int num;
-	int mode;
-	uint16 flags;
+	int16 num;
+	uint32 flags;
 };
 
-struct CUP_Player {
-	Common::File _fd;
-	uint32 _dataSize;
-	int _playbackRate;
-	int _width, _height;
-	uint8 _paletteData[256 * 4];
-	uint8 *_offscreenBuffer;
-	uint8 _tempLzssBuffer[0x1000];
-	uint8 *_currentChunkData;
-	uint32 _currentChunkSize;
-	uint8 *_bufferLzssData;
-	uint32 _bufferLzssSize;
-	bool _paletteChanged;
-	int _sfxCount;
-	uint8 *_sfxBuffer;
-	Audio::SoundHandle *_sfxHandleTable;
-	CUP_Sfx _sfxQueue[16];
-	int _sfxQueuePos;
+struct CUP_SfxChannel {
+	Audio::SoundHandle handle;
+	int16 sfxNum;
+	uint32 flags;
+};
 
-	ScummEngine_vCUPhe *_vm;
-	Audio::Mixer *_mixer;
-	OSystem *_system;
+class CUP_Player {
+public:
 
-	CUP_Player(OSystem *sys, ScummEngine_vCUPhe *vm, Audio::Mixer *mixer) {
-		_currentChunkData = 0;
-		_currentChunkSize = 0;
-		_bufferLzssData = 0;
-		_bufferLzssSize = 0;
-		_vm = vm;
-		_mixer = mixer;
-		_system = sys;
-	}
+	enum {
+		kSfxFlagLoop    = 1 << 0,
+		kSfxFlagRestart = 1 << 1
+	};
 
+	enum {
+		kSfxChannels = 8,
+		kSfxQueueSize = 16,
+		kDefaultPlaybackRate = 66,
+		kDefaultVideoWidth = 640,
+		kDefaultVideoHeight = 480
+	};
+
+	CUP_Player(OSystem *sys, ScummEngine_vCUPhe *vm, Audio::Mixer *mixer);
+
 	bool open(const char *filename);
 	void close();
 	uint32 loadNextChunk();
@@ -73,6 +63,7 @@
 	void setDirtyScreenRect(const Common::Rect &r);
 	void updateScreen();
 	void updateSfx();
+	void waitForSfxChannel(int channel);
 	void parseNextTag(const uint8 *data, uint32 &tag, uint32 &size);
 	void handleHEAD(const uint8 *data, uint32 dataSize);
 	void handleSFXB(const uint8 *data, uint32 dataSize);
@@ -82,10 +73,38 @@
 	void handleSRLE(uint8 *dst, const uint8 *data, uint32 size);
 	void decodeSRLE(uint8 *dst, const uint8 *colorMap, const uint8 *data, int unpackedSize);
 	uint8 *handleLZSS(const uint8 *data, uint32 dataSize);
-	void decodeLzssData(uint8 *dst1, const uint8 *src1, const uint8 *src2, const uint8 *src3, uint8 *dst2);
+	void decodeLZSS(uint8 *dst, const uint8 *src1, const uint8 *src2, const uint8 *src3);
 	void handleRATE(const uint8 *data, uint32 dataSize);
 	void handleSNDE(const uint8 *data, uint32 dataSize);
 	void handleTOIL(const uint8 *data, uint32 dataSize);
+
+protected:
+
+	ScummEngine_vCUPhe *_vm;
+	Audio::Mixer *_mixer;
+	OSystem *_system;
+
+	Common::File _fd;
+	uint32 _dataSize;
+
+	int _playbackRate;
+	int _width, _height;
+
+	uint8 _paletteData[256 * 4];
+	bool _paletteChanged;
+	uint8 *_offscreenBuffer;
+
+	uint8 *_currentChunkData;
+	uint32 _currentChunkSize;
+	uint8 *_bufferLzssData;
+	uint32 _bufferLzssSize;
+
+	int _sfxCount;
+	uint8 *_sfxBuffer;
+	CUP_SfxChannel _sfxChannels[kSfxChannels];
+	CUP_Sfx _sfxQueue[kSfxQueueSize];
+	int _sfxQueuePos;
+	int _lastSfxChannel;
 };
 
 } // End of namespace Scumm

Modified: scummvm/trunk/engines/scumm/he/intern_he.h
===================================================================
--- scummvm/trunk/engines/scumm/he/intern_he.h	2007-01-21 22:06:54 UTC (rev 25157)
+++ scummvm/trunk/engines/scumm/he/intern_he.h	2007-01-21 22:08:02 UTC (rev 25158)
@@ -42,7 +42,7 @@
 class LogicHE;
 class MoviePlayer;
 class Sprite;
-struct CUP_Player;
+class CUP_Player;
 #endif
 
 class ScummEngine_v60he : public ScummEngine_v6 {

Modified: scummvm/trunk/engines/scumm/scumm.cpp
===================================================================
--- scummvm/trunk/engines/scumm/scumm.cpp	2007-01-21 22:06:54 UTC (rev 25157)
+++ scummvm/trunk/engines/scumm/scumm.cpp	2007-01-21 22:08:02 UTC (rev 25158)
@@ -784,7 +784,7 @@
 
 int ScummEngine_vCUPhe::init() {
 	_system->beginGFXTransaction();
-		_system->initSize(640, 480);
+		_system->initSize(CUP_Player::kDefaultVideoWidth, CUP_Player::kDefaultVideoHeight);
 		initCommonGFX(true);
 	_system->endGFXTransaction();
 
@@ -792,10 +792,10 @@
 }
 
 int ScummEngine_vCUPhe::go() {
-	_cupPlayer->open(_filenamePattern.pattern);
-	_cupPlayer->play();
-	_cupPlayer->close();
-
+	if (_cupPlayer->open(_filenamePattern.pattern)) {
+		_cupPlayer->play();
+		_cupPlayer->close();
+	}
 	return 0;
 }
 


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