[Scummvm-cvs-logs] SF.net SVN: scummvm:[35227] scummvm/trunk/engines/gob

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Wed Dec 3 23:14:48 CET 2008


Revision: 35227
          http://scummvm.svn.sourceforge.net/scummvm/?rev=35227&view=rev
Author:   drmccoy
Date:     2008-12-03 22:14:47 +0000 (Wed, 03 Dec 2008)

Log Message:
-----------
Preliminary support for extra data and scripts in video files (urgh, this is so...vile).
Used in The Last Dynasty, which now plays a bit further (the video sequences, at least)

Modified Paths:
--------------
    scummvm/trunk/engines/gob/coktelvideo.cpp
    scummvm/trunk/engines/gob/coktelvideo.h
    scummvm/trunk/engines/gob/dataio.cpp
    scummvm/trunk/engines/gob/game.cpp
    scummvm/trunk/engines/gob/game_v2.cpp
    scummvm/trunk/engines/gob/inter_v4.cpp
    scummvm/trunk/engines/gob/videoplayer.cpp
    scummvm/trunk/engines/gob/videoplayer.h

Modified: scummvm/trunk/engines/gob/coktelvideo.cpp
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.cpp	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/coktelvideo.cpp	2008-12-03 22:14:47 UTC (rev 35227)
@@ -880,8 +880,10 @@
 	uint16 handle = _stream->readUint16LE();
 	_version = _stream->readUint16LE();
 
+	// 0x4 (4)
+
 	// Version checking
-	if ((headerLength != 814) || (handle != 0) || (_version != 1)) {
+	if (headerLength != 814) {
 		warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version);
 		unload();
 		return false;
@@ -889,31 +891,62 @@
 
 	_framesCount = _stream->readUint16LE();
 
+	// 0x6 (6)
+
 	_x = _stream->readSint16LE();
 	_y = _stream->readSint16LE();
 	_width = _stream->readSint16LE();
 	_height = _stream->readSint16LE();
+
+	// 0xE (14)
+
 	if ((_width != 0) && (_height != 0)) {
 		_hasVideo = true;
 		_features |= kFeaturesVideo;
 	} else
 		_hasVideo = false;
 
+	if (_width > 320) {
+		if (!(_version & 4)) {
+			_version |= 4;
+			handle = 0;
+		}
+	}
+
+	if (handle == 0) {
+		// _field_463 = 1;
+	} else if (handle == 1) {
+		// _field_463 = 0;
+	} else if (handle == 2) {
+		// _field_463 = 2;
+	} else {
+		warning("VMD Version incorrect (%d, %d, %d)", headerLength, handle, _version);
+		unload();
+		return false;
+	}
+
 	_flags = _stream->readUint16LE();
 	_partsPerFrame = _stream->readUint16LE();
 	_firstFramePos = _stream->readUint32LE();
 	_stream->skip(4); // Unknown
 
+	// 0x1A (26)
+
 	_stream->read((byte *) _palette, 768);
 
+	// 0x31A (794)
+
 	_frameDataSize = _stream->readUint32LE();
 	_vidBufferSize = _stream->readUint32LE();
 
+	// 0x322 (802)
+
 	if (_hasVideo) {
-		if ((_frameDataSize == 0) || (_frameDataSize > 1048576))
+		_vidBufferSize = _frameDataSize = 312200;
+/*		if ((_frameDataSize == 0) || (_frameDataSize > 1048576))
 			_frameDataSize = _width * _height + 500;
 		if ((_vidBufferSize == 0) || (_vidBufferSize > 1048576))
-			_vidBufferSize = _frameDataSize;
+			_vidBufferSize = _frameDataSize;*/
 
 		_frameData = new byte[_frameDataSize];
 		assert(_frameData);
@@ -929,6 +962,8 @@
 	_soundFlags = _stream->readUint16LE();
 	_hasSound = (_soundFreq != 0);
 
+	// 0x32A (810)
+
 	if (_hasSound) {
 		_features |= kFeaturesSound;
 
@@ -956,6 +991,8 @@
 
 	_frameInfoOffset = _stream->readUint32LE();
 
+	int numExtraData = 0;
+
 	_stream->seek(_frameInfoOffset);
 	_frames = new Frame[_framesCount];
 	for (uint16 i = 0; i < _framesCount; i++) {
@@ -964,6 +1001,8 @@
 		_frames[i].offset = _stream->readUint32LE();
 	}
 	for (uint16 i = 0; i < _framesCount; i++) {
+		bool separator = false;
+
 		for (uint16 j = 0; j < _partsPerFrame; j++) {
 
 			_frames[i].parts[j].type = (PartType) _stream->readByte();
@@ -984,6 +1023,13 @@
 				_stream->skip(1); // Unknown
 				_frames[i].parts[j].flags = _stream->readByte();
 
+			} else if (_frames[i].parts[j].type == kPartTypeExtraData) {
+				if (!separator)
+					numExtraData++;
+				_stream->skip(10);
+			} else if (_frames[i].parts[j].type == kPartTypeSeparator) {
+				separator = true;
+				_stream->skip(10);
 			} else {
 				// Unknow type
 				_stream->skip(10);
@@ -992,6 +1038,45 @@
 		}
 	}
 
+	if (numExtraData == 0)
+		return true;
+
+	_extraData.reserve(numExtraData);
+
+	numExtraData = 0;
+
+	uint32 ssize = _stream->size();
+	for (uint16 i = 0; i < _framesCount; i++) {
+		_stream->seek(_frames[i].offset);
+
+		for (uint16 j = 0; j < _partsPerFrame; j++) {
+			if (_frames[i].parts[j].type == kPartTypeSeparator)
+				break;
+
+			if (_frames[i].parts[j].type == kPartTypeExtraData) {
+				ExtraData data;
+
+				data.offset = _stream->pos() + 20;
+				data.size = _frames[i].parts[j].size;
+				data.realSize = _stream->readUint32LE();
+				_stream->read(data.name, 16);
+				data.name[15] = '\0';
+
+				_stream->skip(_frames[i].parts[j].size - 20);
+
+				if ((((uint32) data.realSize) >= ssize) || (data.name[0] == 0))
+					continue;
+					
+				warning("ExtraData %d: %d.%d, %d, %d, %d, %s", _extraData.size(), i, j,
+						data.offset, data.size, data.realSize, data.name);
+
+				_extraData.push_back(data);
+
+			} else
+				_stream->skip(_frames[i].parts[j].size);
+		}
+	}
+
 	return true;
 }
 
@@ -1057,15 +1142,16 @@
 void Vmd::clear(bool del) {
 	Imd::clear(del);
 
-	if (del) {
+	if (del)
 		delete[] _frames;
-	}
 
 	_hasVideo = true;
 
 	_partsPerFrame = 0;
 	_frames = 0;
 
+	_extraData.clear();
+
 	_soundBytesPerSample = 1;
 	_soundStereo = 0;
 }
@@ -1294,9 +1380,46 @@
 			imdVidMemBak += sW;
 			imdVidMem = imdVidMemBak;
 		}
-	} else {
-		warning("Unkown frame rendering method %d (0x%X)", type, type);
-		return 0;
+	} else if (type == 0x42) { // Whole quarter-wide block
+		for (int i = 0; i < height; i++) {
+			imdVidMemBak = imdVidMem;
+
+			for (int j = 0; j < width; j += 4, imdVidMem += 4, srcPtr++)
+				memset(imdVidMem, *srcPtr, 4);
+
+			imdVidMemBak += sW;
+			imdVidMem = imdVidMemBak;
+		}
+	} else if ((type & 0xF) == 2) { // Whole half-high block
+		for (; height > 1; height -= 2, imdVidMem += sW + sW, srcPtr += width) {
+			memcpy(imdVidMem, srcPtr, width);
+			memcpy(imdVidMem + sW, srcPtr, width);
+		}
+		if (height == -1)
+			memcpy(imdVidMem, srcPtr, width);
+	} else { // Sparse half-high block
+		imdVidMemBak = imdVidMem;
+		for (int i = 0; i < height; i += 2) {
+			pixWritten = 0;
+			while (pixWritten < width) {
+				pixCount = *srcPtr++;
+				if (pixCount & 0x80) { // Data
+					pixCount = MIN((pixCount & 0x7F) + 1, width - pixWritten);
+					memcpy(imdVidMem, srcPtr, pixCount);
+					memcpy(imdVidMem + sW, srcPtr, pixCount);
+
+					pixWritten += pixCount;
+					imdVidMem += pixCount;
+					srcPtr += pixCount;
+				} else { // "Hole"
+					pixCount = (pixCount + 1) % 256;
+					pixWritten += pixCount;
+					imdVidMem += pixCount;
+				}
+			}
+			imdVidMemBak += sW + sW;
+			imdVidMem = imdVidMemBak;
+		}
 	}
 
 	return 1;
@@ -1387,7 +1510,7 @@
 	for (i = 0; i < _partsPerFrame; i++) {
 		byte type = _stream->readByte();
 
-		if ((type == 0) || (type == partType))
+		if ((type == kPartTypeSeparator) || (type == partType))
 			break;
 
 		_stream->skip(15);
@@ -1410,4 +1533,45 @@
 	return true;
 }
 
+bool Vmd::hasExtraData(const char *fileName) const {
+	for (uint i = 0; i < _extraData.size(); i++)
+		if (!scumm_stricmp(_extraData[i].name, fileName))
+			return true;
+
+	return false;
+}
+
+Common::MemoryReadStream *Vmd::getExtraData(const char *fileName) {
+	uint i = 0;
+
+	for (i = 0; i < _extraData.size(); i++)
+		if (!scumm_stricmp(_extraData[i].name, fileName))
+			break;
+
+	if (i >= _extraData.size())
+		return 0;
+
+	if ((_extraData[i].size - 20) != _extraData[i].realSize) {
+		warning("Vmd::getExtraData(): Sizes for \"%s\" differ! (%d, %d)",
+				fileName, (_extraData[i].size - 20), _extraData[i].realSize);
+		return 0;
+	}
+
+	byte *data = (byte *) malloc(_extraData[i].realSize);
+
+	_stream->seek(_extraData[i].offset);
+	if (_stream->ioFailed() || (((uint32) _stream->pos()) != _extraData[i].offset)) {
+		warning("Vmd::getExtraData(): Can't seek to offset %d to get extra data file \"%s\"",
+				_extraData[i].offset, fileName);
+		return 0;
+	}
+
+	_stream->read(data, _extraData[i].realSize);
+
+	Common::MemoryReadStream *stream =
+		new Common::MemoryReadStream(data, _extraData[i].realSize, true);
+
+	return stream;
+}
+
 } // End of namespace Gob

Modified: scummvm/trunk/engines/gob/coktelvideo.h
===================================================================
--- scummvm/trunk/engines/gob/coktelvideo.h	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/coktelvideo.h	2008-12-03 22:14:47 UTC (rev 35227)
@@ -27,6 +27,7 @@
 #define GOB_COKTELVIDEO_H
 
 #include "common/stream.h"
+#include "common/array.h"
 #include "sound/mixer.h"
 #include "sound/audiostream.h"
 
@@ -119,6 +120,11 @@
 	virtual bool getAnchor(int16 frame, uint16 partType,
 			int16 &x, int16 &y, int16 &width, int16 &height) = 0;
 
+	/** Returns whether that extra data file exists */
+	virtual bool hasExtraData(const char *fileName) const = 0;
+	/** Returns an extra data file */
+	virtual Common::MemoryReadStream *getExtraData(const char *fileName) = 0;
+
 	/** Load a video out of a stream. */
 	virtual bool load(Common::SeekableReadStream &stream) = 0;
 	/** Unload the currently loaded video. */
@@ -201,6 +207,9 @@
 	bool getAnchor(int16 frame, uint16 partType,
 			int16 &x, int16 &y, int16 &width, int16 &height) { return false; }
 
+	bool hasExtraData(const char *fileName) const { return false; }
+	Common::MemoryReadStream *getExtraData(const char *fileName) { return 0; }
+
 	void setFrameRate(int16 frameRate);
 
 	bool load(Common::SeekableReadStream &stream);
@@ -295,6 +304,9 @@
 	bool getAnchor(int16 frame, uint16 partType,
 			int16 &x, int16 &y, int16 &width, int16 &height);
 
+	bool hasExtraData(const char *fileName) const;
+	Common::MemoryReadStream *getExtraData(const char *fileName);
+
 	bool load(Common::SeekableReadStream &stream);
 	void unload();
 
@@ -306,9 +318,17 @@
 
 protected:
 	enum PartType {
+		kPartTypeSeparator = 0,
 		kPartTypeAudio = 1,
-		kPartTypeVideo = 2
+		kPartTypeVideo = 2,
+		kPartTypeExtraData = 3
 	};
+	struct ExtraData {
+		char name[16];
+		uint32 offset;
+		uint32 size;
+		uint32 realSize;
+	} PACKED_STRUCT;
 	struct Part {
 		PartType type;
 		uint32 size;
@@ -334,6 +354,8 @@
 	uint16 _partsPerFrame;
 	Frame *_frames;
 
+	Common::Array<ExtraData> _extraData;
+
 	byte _soundBytesPerSample;
 	byte _soundStereo; // (0: mono, 1: old-style stereo, 2: new-style stereo)
 

Modified: scummvm/trunk/engines/gob/dataio.cpp
===================================================================
--- scummvm/trunk/engines/gob/dataio.cpp	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/dataio.cpp	2008-12-03 22:14:47 UTC (rev 35227)
@@ -312,8 +312,10 @@
 	_isCurrentSlot[index] = false;
 	if (from == SEEK_SET)
 		_chunkPos[index] = pos;
-	else
+	else if (from == SEEK_CUR)
 		_chunkPos[index] += pos;
+	else if (from == SEEK_END)
+		_chunkPos[index] = _chunkSize[index] - pos;
 
 	return _chunkPos[index];
 }

Modified: scummvm/trunk/engines/gob/game.cpp
===================================================================
--- scummvm/trunk/engines/gob/game.cpp	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/game.cpp	2008-12-03 22:14:47 UTC (rev 35227)
@@ -34,6 +34,7 @@
 #include "gob/parse.h"
 #include "gob/draw.h"
 #include "gob/mult.h"
+#include "gob/videoplayer.h"
 #include "gob/sound/sound.h"
 
 namespace Gob {
@@ -394,9 +395,20 @@
 		_vm->_dataIO->closeData(handle);
 		size = _vm->_dataIO->getDataSize(path);
 		_totFileData = _vm->_dataIO->getData(path);
-	} else
-		_totFileData = 0;
+	} else {
+		Common::MemoryReadStream *videoExtraData = _vm->_vidPlayer->getExtraData(path);
 
+		if (videoExtraData) {
+			warning("Found \"%s\" in video file", path);
+
+			size = videoExtraData->size();
+			_totFileData = new byte[size];
+			videoExtraData->read(_totFileData, size);
+			delete videoExtraData;
+		} else
+			_totFileData = 0;
+	}
+
 	return size;
 }
 

Modified: scummvm/trunk/engines/gob/game_v2.cpp
===================================================================
--- scummvm/trunk/engines/gob/game_v2.cpp	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/game_v2.cpp	2008-12-03 22:14:47 UTC (rev 35227)
@@ -106,6 +106,9 @@
 				break;
 
 			totSize = loadTotFile(_curTotFile);
+
+			_vm->_vidPlayer->primaryClose();
+
 			if (_totFileData == 0) {
 				_vm->_draw->blitCursor();
 				_vm->_inter->_terminate = 2;
@@ -269,7 +272,6 @@
 				}
 			}
 
-			_vm->_vidPlayer->primaryClose();
 			if (_totToLoad[0] == 0)
 				break;
 

Modified: scummvm/trunk/engines/gob/inter_v4.cpp
===================================================================
--- scummvm/trunk/engines/gob/inter_v4.cpp	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/inter_v4.cpp	2008-12-03 22:14:47 UTC (rev 35227)
@@ -834,6 +834,7 @@
 	close = false;
 	if (lastFrame == -1) {
 		close = true;
+	} else if (lastFrame == -2) {
 	} else if (lastFrame == -3) {
 
 		_vm->_mult->_objects[startFrame].pAnimData->animation = -startFrame - 1;
@@ -878,7 +879,8 @@
 	}
 
 	if (startFrame == -2) {
-		startFrame = lastFrame = 0;
+		startFrame = 0;
+		lastFrame = -1;
 		close = false;
 	}
 

Modified: scummvm/trunk/engines/gob/videoplayer.cpp
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.cpp	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/videoplayer.cpp	2008-12-03 22:14:47 UTC (rev 35227)
@@ -124,6 +124,20 @@
 	return _defaultY;
 }
 
+bool VideoPlayer::Video::hasExtraData(const char *fileName) const {
+	if (!_video)
+		return false;
+
+	return _video->hasExtraData(fileName);
+}
+
+Common::MemoryReadStream *VideoPlayer::Video::getExtraData(const char *fileName) {
+	if (!_video)
+		return 0;
+
+	return _video->getExtraData(fileName);
+}
+
 CoktelVideo::State VideoPlayer::Video::nextFrame() {
 	if (_video)
 		_state = _video->nextFrame();
@@ -445,6 +459,16 @@
 	return 0;
 }
 
+VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) {
+	if (slot < 0) {
+		if (_primaryVideo->isOpen())
+			return _primaryVideo;
+	} else if (((uint) slot) < _videoSlots.size() && _videoSlots[slot])
+		return _videoSlots[slot];
+
+	return 0;
+}
+
 uint16 VideoPlayer::getFlags(int slot) const {
 	const Video *video = getVideoBySlot(slot);
 
@@ -508,6 +532,24 @@
 	return 0;
 }
 
+bool VideoPlayer::hasExtraData(const char *fileName, int slot) const {
+	const Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->hasExtraData(fileName);
+
+	return false;
+}
+
+Common::MemoryReadStream *VideoPlayer::getExtraData(const char *fileName, int slot) {
+	Video *video = getVideoBySlot(slot);
+
+	if (video)
+		return video->getExtraData(fileName);
+
+	return 0;
+}
+
 bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
 		uint16 palCmd, int16 palStart, int16 palEnd,
 		int16 palFrame, int16 endFrame) {

Modified: scummvm/trunk/engines/gob/videoplayer.h
===================================================================
--- scummvm/trunk/engines/gob/videoplayer.h	2008-12-03 21:52:51 UTC (rev 35226)
+++ scummvm/trunk/engines/gob/videoplayer.h	2008-12-03 22:14:47 UTC (rev 35227)
@@ -80,6 +80,9 @@
 	int16 getDefaultX(int slot = -1) const;
 	int16 getDefaultY(int slot = -1) const;
 
+	bool hasExtraData(const char *fileName, int slot = -1) const;
+	Common::MemoryReadStream *getExtraData(const char *fileName, int slot = -1);
+
 	void writeVideoInfo(const char *videoFile, int16 varX, int16 varY,
 			int16 varFrames, int16 varWidth, int16 varHeight);
 
@@ -104,6 +107,9 @@
 			int16 getDefaultX() const;
 			int16 getDefaultY() const;
 
+			bool hasExtraData(const char *fileName) const;
+			Common::MemoryReadStream *getExtraData(const char *fileName);
+
 			CoktelVideo::State nextFrame();
 
 		private:
@@ -129,6 +135,7 @@
 	bool findFile(char *fileName, Type &which);
 
 	const Video *getVideoBySlot(int slot = -1) const;
+	Video *getVideoBySlot(int slot = -1);
 
 	int getNextFreeSlot();
 


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