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

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Tue Feb 8 20:50:46 CET 2011


Revision: 55830
          http://scummvm.svn.sourceforge.net/scummvm/?rev=55830&view=rev
Author:   thebluegr
Date:     2011-02-08 19:50:45 +0000 (Tue, 08 Feb 2011)

Log Message:
-----------
SCI: Some work on robot videos

- The size of the videos is now calculated when they are loaded (this helps remove some
nasty hacks and constant memory reallocations and simplifies the code)
- Some work on frame placement (e.g. in robot 1305, Phantasmagoria)

Modified Paths:
--------------
    scummvm/trunk/engines/sci/engine/kvideo.cpp
    scummvm/trunk/engines/sci/video/robot_decoder.cpp
    scummvm/trunk/engines/sci/video/robot_decoder.h

Modified: scummvm/trunk/engines/sci/engine/kvideo.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kvideo.cpp	2011-02-08 17:32:40 UTC (rev 55829)
+++ scummvm/trunk/engines/sci/engine/kvideo.cpp	2011-02-08 19:50:45 UTC (rev 55830)
@@ -51,15 +51,12 @@
 	uint16 screenWidth = g_system->getWidth();
 	uint16 screenHeight = g_system->getHeight();
 	bool isVMD = videoState.fileName.hasSuffix(".vmd");
-	bool isRobot = videoState.fileName.hasSuffix(".rbt");
 
-	if (!isRobot) {
-		if (screenWidth == 640 && width <= 320 && height <= 240 && ((videoState.flags & kDoubled) || !isVMD)) {
-			width *= 2;
-			height *= 2;
-			pitch *= 2;
-			scaleBuffer = new byte[width * height * bytesPerPixel];
-		}
+	if (screenWidth == 640 && width <= 320 && height <= 240 && ((videoState.flags & kDoubled) || !isVMD)) {
+		width *= 2;
+		height *= 2;
+		pitch *= 2;
+		scaleBuffer = new byte[width * height * bytesPerPixel];
 	}
 
 	uint16 x, y; 
@@ -76,13 +73,8 @@
 			y = (screenHeight - height) / 2;
 		}
 	} else {
-		if (!isRobot) {
 			x = (screenWidth - width) / 2;
 			y = (screenHeight - height) / 2;
-		} else {
-			x = 0;
-			y = 0;
-		}
 	}
 	bool skipVideo = false;
 
@@ -99,10 +91,7 @@
 					g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight(), bytesPerPixel);
 					g_system->copyRectToScreen(scaleBuffer, pitch, x, y, width, height);
 				} else {
-					if (!isRobot)
-						g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height);
-					else	// Frames in robot videos have different dimensions
-						g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h);
+					g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height);
 				}
 
 				if (videoDecoder->hasDirtyPalette())

Modified: scummvm/trunk/engines/sci/video/robot_decoder.cpp
===================================================================
--- scummvm/trunk/engines/sci/video/robot_decoder.cpp	2011-02-08 17:32:40 UTC (rev 55829)
+++ scummvm/trunk/engines/sci/video/robot_decoder.cpp	2011-02-08 19:50:45 UTC (rev 55830)
@@ -76,6 +76,8 @@
 
 RobotDecoder::RobotDecoder(Audio::Mixer *mixer, bool isBigEndian) {
 	_surface = 0;
+	_width = 0;
+	_height = 0;
 	_fileStream = 0;
 	_audioStream = 0;
 	_dirtyPalette = false;
@@ -123,6 +125,9 @@
 
 	readPaletteChunk(_header.paletteDataSize);
 	readFrameSizesChunk();
+	calculateVideoDimensions();
+	_surface->create(_width, _height, 1);
+
 	return true;
 }
 
@@ -218,31 +223,56 @@
 		_fileStream->seek((curPos & ~0x7ff) + 2048);
 }
 
+void RobotDecoder::calculateVideoDimensions() {
+	// This is an O(n) operation, as each frame has a different size.
+	// We need to know the actual frame size to have a constant video size.
+	uint32 pos = _fileStream->pos();
+	
+	for (uint32 curFrame = 0; curFrame < _header.frameCount; curFrame++) {
+		_fileStream->skip(4);
+		uint16 frameWidth = _fileStream->readUint16();
+		uint16 frameHeight = _fileStream->readUint16();
+		if (frameWidth > _width)
+			_width = frameWidth;
+		if (frameHeight > _height)
+			_height = frameHeight;
+		_fileStream->skip(_frameTotalSize[curFrame] - 8);
+	}
+
+	_fileStream->seek(pos);
+}
+
 const Graphics::Surface *RobotDecoder::decodeNextFrame() {
 	// Read frame image header (24 bytes)
 	_fileStream->skip(3);
 	byte frameScale = _fileStream->readByte();
 	uint16 frameWidth = _fileStream->readUint16();
 	uint16 frameHeight = _fileStream->readUint16();
-	_fileStream->skip(8); // x, y, width and height of the frame
+	_fileStream->skip(4); // unknown, almost always 0
+	uint16 frameX = _fileStream->readUint16();
+	uint16 frameY = _fileStream->readUint16();
 	uint16 compressedSize = _fileStream->readUint16();
 	uint16 frameFragments = _fileStream->readUint16();
 	_fileStream->skip(4); // unknown
-
 	uint32 decompressedSize = frameWidth * frameHeight * frameScale / 100;
-	_surface->free();
-	_surface->create(frameWidth, frameHeight, 1);
-	_surface->w = frameWidth * frameScale / 100;
+	// FIXME: A frame's height + position can go off limits... why? With the
+	// following, we cut the contents to fit the frame
+	uint16 scaledHeight = CLIP<uint16>(decompressedSize / frameWidth, 0, _height - frameY);
+	// FIXME: Same goes for the frame's width + position. In this case, we
+	// modify the position to fit the contents on screen.
+	if (frameWidth + frameX > _width)
+		frameX = _width - frameWidth;
+	assert (frameWidth + frameX <= _width && scaledHeight + frameY <= _height);
 
 	DecompressorLZS lzs;
+	byte *decompressedFrame = new byte[decompressedSize];
+	byte *outPtr = decompressedFrame;
 
 	if (_header.version == 4) {
 		// v4 has just the one fragment, it seems, and ignores the fragment count
 		Common::SeekableSubReadStream fragmentStream(_fileStream, _fileStream->pos(), _fileStream->pos() + compressedSize);
-		lzs.unpack(&fragmentStream, (byte *)_surface->pixels, compressedSize, decompressedSize);
+		lzs.unpack(&fragmentStream, outPtr, compressedSize, decompressedSize);
 	} else {
-		byte *outPtr = (byte *)_surface->pixels;
-
 		for (uint16 i = 0; i < frameFragments; ++i) {
 			uint32 compressedFragmentSize = _fileStream->readUint32();
 			uint32 decompressedFragmentSize = _fileStream->readUint32();
@@ -261,6 +291,24 @@
 		}
 	}
 
+	// Copy over the decompressed frame
+	byte *inFrame = decompressedFrame;
+	byte *outFrame = (byte *)_surface->pixels;
+
+	// Black out the surface
+	memset(outFrame, 0, _width * _height);
+
+	// Move to the correct y coordinate
+	outFrame += _width * frameY;
+
+	for (uint16 y = 0; y < scaledHeight; y++) {
+		memcpy(outFrame + frameX, inFrame, frameWidth);
+		inFrame += frameWidth;
+		outFrame += _width;
+	}
+
+	delete[] decompressedFrame;
+
 	// +1 because we start with frame number -1
 	uint32 audioChunkSize = _frameTotalSize[_curFrame + 1] - (24 + compressedSize);
 

Modified: scummvm/trunk/engines/sci/video/robot_decoder.h
===================================================================
--- scummvm/trunk/engines/sci/video/robot_decoder.h	2011-02-08 17:32:40 UTC (rev 55829)
+++ scummvm/trunk/engines/sci/video/robot_decoder.h	2011-02-08 19:50:45 UTC (rev 55830)
@@ -62,9 +62,8 @@
 	void close();
 
 	bool isVideoLoaded() const { return _fileStream != 0; }
-	uint16 getWidth() const { assert(_surface); return _surface->w; }
-	uint16 getHeight() const { assert(_surface); return _surface->h; }
-	uint16 getPitch() const { assert(_surface); return _surface->pitch; }
+	uint16 getWidth() const { return _width; }
+	uint16 getHeight() const { return _height; }
 	uint32 getFrameCount() const { return _header.frameCount; }
 	const Graphics::Surface *decodeNextFrame();
 	Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }
@@ -80,6 +79,7 @@
 	void readHeaderChunk();
 	void readPaletteChunk(uint16 chunkSize);
 	void readFrameSizesChunk();
+	void calculateVideoDimensions();
 
 	void freeData();
 
@@ -89,6 +89,8 @@
 
 	Common::SeekableSubReadStreamEndian *_fileStream;
 
+	uint16 _width;
+	uint16 _height;
 	uint32 *_frameTotalSize;
 	byte _palette[256 * 3];
 	bool _dirtyPalette;


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