[Scummvm-cvs-logs] SF.net SVN: scummvm:[55752] scummvm/trunk/engines/sci

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Thu Feb 3 15:37:50 CET 2011


Revision: 55752
          http://scummvm.svn.sourceforge.net/scummvm/?rev=55752&view=rev
Author:   thebluegr
Date:     2011-02-03 14:37:50 +0000 (Thu, 03 Feb 2011)

Log Message:
-----------
SCI21: Some robot related changes

- Don't reallocate the frame buffer on each update if its dimensions haven't changed
- Don't attempt to display the currently unsupported v4 robot files (used in PQ:SWAT)
- Signed/unsigned fixes
- Disabled the unused getFrameRect() function
- Some cleanup and reordering

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kgraphics.cpp
    scummvm/trunk/engines/sci/graphics/robot.cpp
    scummvm/trunk/engines/sci/graphics/robot.h

Modified: scummvm/trunk/engines/sci/engine/kgraphics.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kgraphics.cpp	2011-02-03 12:42:52 UTC (rev 55751)
+++ scummvm/trunk/engines/sci/engine/kgraphics.cpp	2011-02-03 14:37:50 UTC (rev 55752)
@@ -1414,14 +1414,17 @@
 		case 1:	// LSL6 hires (startup)
 			// TODO
 			return NULL_REG;	// an integer is expected
-		case 4: {	// start
-				int id = argv[1].toUint16();
-				warning("kRobot(start), id %d", id);
+		case 4: {	// start - we don't really have a use for this one
+				//int id = argv[1].toUint16();
+				//warning("kRobot(start), id %d", id);
 			}
 			break;
+		case 7:	// unknown, called e.g. by Phantasmagoria
+			warning("kRobot(%d)", subop);
+			break;
 		case 8: // sync
 			robot->drawNextFrame();
-			// Sync
+			// Signal the engine scripts that the video is done
 			if (robot->getCurFrame() ==  robot->getFrameCount())
 				writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG);
 			break;

Modified: scummvm/trunk/engines/sci/graphics/robot.cpp
===================================================================
--- scummvm/trunk/engines/sci/graphics/robot.cpp	2011-02-03 12:42:52 UTC (rev 55751)
+++ scummvm/trunk/engines/sci/graphics/robot.cpp	2011-02-03 14:37:50 UTC (rev 55752)
@@ -62,13 +62,17 @@
 #ifdef ENABLE_SCI32
 GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette)
 	: _resMan(resMan), _screen(screen), _palette(palette), _resourceData(0),
-	  _imageStart(0), _audioStart(0), _audioLen(0) {
+	  _imageStart(0), _audioStart(0), _audioLen(0), _outputBuffer(0), _outputBufferSize(0) {
 	_resourceId = -1;
 	_x = _y = 0;
 }
 
 GfxRobot::~GfxRobot() {
-	freeData();
+	delete[] _resourceData;
+	delete[] _imageStart;
+	delete[] _audioStart;
+	delete[] _audioLen;
+	delete[] _outputBuffer;
 }
 
 void GfxRobot::init(GuiResourceId resourceId, uint16 x, uint16 y) {
@@ -94,6 +98,13 @@
 		return;
 	}
 
+	// There are several versions of robot files, ranging from 3 to 6. Version
+	// 5 is the version of the majority of the robot files. PQ:SWAT is the only
+	// game that uses robots of a different version (version 4), but there are
+	// no known examples of other robot versions.
+	_version = _resourceData[6];
+
+	// Currently, we only support robot version 5. Robot version 
 	_frameCount = READ_LE_UINT16(_resourceData + 14);
 
 	// There is another value in the header, at offset 0x12, which
@@ -114,6 +125,20 @@
 	if (_hasSound && READ_LE_UINT16(_resourceData + 10) == 0)
 		_palOffset += READ_LE_UINT32(_resourceData + 60) + 14;
 
+	switch (_version) {
+	case 4:
+		// TODO: Add support for this version (used in PQ:SWAT)
+		warning("TODO: add support for v4 robot videos");
+		_curFrame = _frameCount;	// jump to the last frame
+		return;
+	case 5:
+		// Supported, the most well-known and used version
+		break;
+	default:
+		// Unsupported, error out so that we find out where this is used
+		error("Unknown robot version: %d", _version);
+	}
+
 	getFrameOffsets();
 	assert(_imageStart[_frameCount] == fileSize);
 
@@ -122,6 +147,40 @@
 	debug("Robot %d, %d frames, sound: %s\n", resourceId, _frameCount, _hasSound ? "yes" : "no");
 }
 
+void GfxRobot::getFrameOffsets() {
+	int *audioEnd = new int[_frameCount];
+	int *videoEnd = new int[_frameCount];
+
+	for (int i = 0; i < _frameCount; ++i) {
+		videoEnd[i] = READ_LE_UINT16(_resourceData + _palOffset + 1200 + i * 2);
+		audioEnd[i] = READ_LE_UINT16(_resourceData + _palOffset + 1200 + _frameCount * 2 + i * 2);
+	}
+
+	uint32 frameDataOffset = _palOffset + 0x4b0 + 0x400 + 0x200 + _frameCount * 4;
+	
+	// Pad to nearest 2 kilobytes
+	if (frameDataOffset & 0x7ff)
+		frameDataOffset = (frameDataOffset & ~0x7ff) + 0x800;
+
+	_imageStart = new uint32[_frameCount + 1];
+	_audioStart = new uint32[_frameCount];
+	_audioLen = new uint32[_frameCount];
+
+	_imageStart[0] = frameDataOffset;
+
+	// Plus one so we can assert on this in the calling routine
+	// The last one should point to end-of-file, unless I'm misunderstanding something
+	for (int i = 1; i < _frameCount + 1; ++i) 
+		_imageStart[i] = _imageStart[i - 1] + audioEnd[i - 1];
+	for (int i = 0; i < _frameCount; ++i)
+		_audioStart[i] = _imageStart[i] + videoEnd[i];
+	for (int i = 0; i < _frameCount; ++i)
+		_audioLen[i] = _imageStart[i + 1] - _audioStart[i];
+
+	delete[] audioEnd;
+	delete[] videoEnd;
+}
+
 void GfxRobot::setPalette() {
 	byte *paletteData = _resourceData + _palOffset;
 	uint16 paletteSize = READ_LE_UINT16(_resourceData + 16);
@@ -157,101 +216,79 @@
 }
 
 void GfxRobot::drawNextFrame() {
-	int width, height;
+	uint16 width, height;
 
-	byte *pixels = assembleVideoFrame(_curFrame);
+	// Make sure that we haven't reached the end of the video already
+	if (_curFrame == _frameCount)
+		return;
+
+	assembleVideoFrame(_curFrame);
 	getFrameDimensions(_curFrame, width, height);
-	g_system->copyRectToScreen(pixels, width, _x, _y, width, height * getFrameScale(_curFrame) / 100);
+	
+	g_system->copyRectToScreen(_outputBuffer, width, _x, _y, width, height * getFrameScale(_curFrame) / 100);
 	g_system->updateScreen();
 	g_system->delayMillis(100);
-	delete[] pixels;
 
 	_curFrame++;
 
 	if (_curFrame == _frameCount) {
 		// End of robot video, restore palette
 		g_system->setPalette(_savedPal, 0, 256);
-		freeData();
 		_resourceId = -1;
+		delete[] _outputBuffer;
+		_outputBuffer = 0;
 	}
 }
 
-void GfxRobot::getFrameOffsets() {
-	int *audioEnd = new int[_frameCount];
-	int *videoEnd = new int[_frameCount];
-
-	for (int i = 0; i < _frameCount; ++i) {
-		videoEnd[i] = READ_LE_UINT16(_resourceData + _palOffset + 1200 + i * 2);
-		audioEnd[i] = READ_LE_UINT16(_resourceData + _palOffset + 1200 + _frameCount * 2 + i * 2);
-	}
-
-	int frameDataOffset = _palOffset + 0x4b0 + 0x400 + 0x200 + _frameCount * 4;
-	
-	// Pad to nearest 2 kilobytes
-	if (frameDataOffset & 0x7ff)
-		frameDataOffset = (frameDataOffset & ~0x7ff)+0x800;
-
-	_imageStart = new uint32[_frameCount + 1];
-	_audioStart = new uint32[_frameCount];
-	_audioLen = new uint32[_frameCount];
-
-	_imageStart[0] = frameDataOffset;
-
-	// Plus one so we can assert on this in the calling routine
-	// The last one should point to end-of-file, unless I'm misunderstanding something
-	for (int i = 1; i < _frameCount + 1; ++i) 
-		_imageStart[i] = _imageStart[i - 1] + audioEnd[i - 1];
-	for (int i = 0; i < _frameCount; ++i)
-		_audioStart[i] = _imageStart[i] + videoEnd[i];
-	for (int i = 0; i < _frameCount; ++i)
-		_audioLen[i] = _imageStart[i + 1] - _audioStart[i];
-
-	delete[] audioEnd;
-	delete[] videoEnd;
-}
-
-byte *GfxRobot::assembleVideoFrame(int frame) {
+void GfxRobot::assembleVideoFrame(uint16 frame) {
 	byte *videoData = _resourceData + _imageStart[frame];
-	int frameWidth = READ_LE_UINT16(videoData + 4);
-	int frameHeight = READ_LE_UINT16(videoData + 6);
-	int frameFragments = READ_LE_UINT16(videoData + 18);
+	uint16 frameWidth = READ_LE_UINT16(videoData + 4);
+	uint16 frameHeight = READ_LE_UINT16(videoData + 6);
+	uint16 frameFragments = READ_LE_UINT16(videoData + 18);
 
-	int decompressedSize = 0;
+	uint32 decompressedSize = 0;
 
 	DecompressorLZS lzs;
 
 	videoData = _resourceData + _imageStart[frame] + 24;
 	
 	for (int i = 0; i < frameFragments; ++i) {
-		int fragmentCompressed = READ_LE_UINT32(videoData);
-		int fragmentUncompressed = READ_LE_UINT32(videoData + 4);
+		uint32 fragmentCompressed = READ_LE_UINT32(videoData);
+		uint32 fragmentUncompressed = READ_LE_UINT32(videoData + 4);
 
 		decompressedSize += fragmentUncompressed;
 		videoData += 10 + fragmentCompressed;
 	}
 
-	assert(decompressedSize == (frameWidth * frameHeight) * getFrameScale(frame) / 100);
+	assert(decompressedSize == (uint32)(frameWidth * frameHeight) * getFrameScale(frame) / 100);
+	
+	// Reallocate the output buffer, if its size has changed
+	if (decompressedSize != _outputBufferSize) {
+		delete[] _outputBuffer;
+		_outputBuffer = new byte[decompressedSize];
+	}
 
-	byte *output = new byte[decompressedSize];
-	int assemblePtr = 0;
+	_outputBufferSize = decompressedSize;
 
+	uint32 assemblePtr = 0;
+
 	videoData = _resourceData + _imageStart[frame] + 24;
 
 	for (int i = 0; i < frameFragments; ++i) {
-		int fragmentCompressed = READ_LE_UINT32(videoData);
-		int fragmentUncompressed = READ_LE_UINT32(videoData + 4);
+		uint32 fragmentCompressed = READ_LE_UINT32(videoData);
+		uint32 fragmentUncompressed = READ_LE_UINT32(videoData + 4);
 		uint16 compressionType = READ_LE_UINT16(videoData + 8);
 
 		switch (compressionType) {
 		case 0: {
 			Common::MemoryReadStream compressedFrame(videoData + 10, fragmentCompressed, DisposeAfterUse::NO);
 
-			lzs.unpack(&compressedFrame, output + assemblePtr, fragmentCompressed, fragmentUncompressed);
+			lzs.unpack(&compressedFrame, _outputBuffer + assemblePtr, fragmentCompressed, fragmentUncompressed);
 			assemblePtr += fragmentUncompressed;
 			break;
 		}
 		case 2: // Untested
-			memcpy(output + assemblePtr, videoData + 10, fragmentCompressed);
+			memcpy(_outputBuffer + assemblePtr, videoData + 10, fragmentCompressed);
 			assemblePtr += fragmentUncompressed;
 			break;
 		}
@@ -262,32 +299,32 @@
 	assert(assemblePtr == decompressedSize);
 
 	//	FILE *f = fopen("/tmp/flap", "w");
-	//      fwrite(output, 1, decompressedSize, f);
+	//      fwrite(_outputBuffer, 1, decompressedSize, f);
 	//      fclose(f);
 	//      exit(1);
-
-	return output;
 }
 
-void GfxRobot::getFrameDimensions(int frame, int &width, int &height) {
+void GfxRobot::getFrameDimensions(uint16 frame, uint16 &width, uint16 &height) {
 	byte *videoData = _resourceData + _imageStart[frame];
 
 	width = READ_LE_UINT16(videoData + 4);
 	height = READ_LE_UINT16(videoData + 6);
 }
 
-void GfxRobot::getFrameRect(int frame, Common::Rect &rect) {
+#if 0
+Common::Rect GfxRobot::getFrameRect(uint16 frame) {
 	byte *videoData = _resourceData + _imageStart[frame];
 
-	int x = READ_LE_UINT16(videoData + 8);
-	int y = READ_LE_UINT16(videoData + 10);
-	int w = READ_LE_UINT16(videoData + 12);
-	int h = READ_LE_UINT16(videoData + 14);
+	uint16 x = READ_LE_UINT16(videoData + 8);
+	uint16 y = READ_LE_UINT16(videoData + 10);
+	uint16 w = READ_LE_UINT16(videoData + 12);
+	uint16 h = READ_LE_UINT16(videoData + 14);
 
-	rect = Common::Rect(x, y, x + w, y + h); 
+	return Common::Rect(x, y, x + w, y + h); 
 }
+#endif
 
-int GfxRobot::getFrameScale(int frame) {
+byte GfxRobot::getFrameScale(uint16 frame) {
 	byte *videoData = _resourceData + _imageStart[frame];
 	return videoData[3];
 }
@@ -300,13 +337,13 @@
 	}
 }
 
-void GfxRobot::freeData()
-{
+void GfxRobot::freeData() {
 	delete[] _resourceData; _resourceData = 0;
 	delete[] _imageStart; _imageStart = 0;
 	delete[] _audioStart; _audioStart = 0;
 	delete[] _audioLen; _audioLen = 0;
 }	
+
 #endif
 
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/graphics/robot.h
===================================================================
--- scummvm/trunk/engines/sci/graphics/robot.h	2011-02-03 12:42:52 UTC (rev 55751)
+++ scummvm/trunk/engines/sci/graphics/robot.h	2011-02-03 14:37:50 UTC (rev 55752)
@@ -46,10 +46,13 @@
 private:
 	void initData(GuiResourceId resourceId);
 	void getFrameOffsets();
-	byte *assembleVideoFrame(int frame);
-	void getFrameDimensions(int frame, int &width, int &height);
-	void getFrameRect(int frame, Common::Rect &rect); // Not sure what to use this for yet
-	int getFrameScale(int frame); // Scale factor (multiplied by 100). More like custom height, but why use a percentage for it?
+	void assembleVideoFrame(uint16 frame);
+	void getFrameDimensions(uint16 frame, uint16 &width, uint16 &height);
+#if 0
+	// Unused
+	Common::Rect getFrameRect(uint16 frame);
+#endif
+	byte getFrameScale(uint16 frame); // Scale factor (multiplied by 100). More like custom height, but why use a percentage for it?
 	void setPalette();
 	void freeData();
 
@@ -61,6 +64,7 @@
 	byte *_resourceData;
 	byte _savedPal[256 * 4];
 
+	byte _version;	// robot version
 	uint16 _x;
 	uint16 _y;
 	//uint16 _width;
@@ -74,6 +78,9 @@
 	uint32 *_audioStart;
 	uint32 *_audioLen;
 	uint16 _curFrame;
+
+	byte *_outputBuffer;
+	uint32 _outputBufferSize;
 };
 #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