[Scummvm-cvs-logs] SF.net SVN: scummvm:[55263] scummvm/trunk/graphics/video

drmccoy at users.sourceforge.net drmccoy at users.sourceforge.net
Sun Jan 16 17:29:44 CET 2011


Revision: 55263
          http://scummvm.svn.sourceforge.net/scummvm/?rev=55263&view=rev
Author:   drmccoy
Date:     2011-01-16 16:29:43 +0000 (Sun, 16 Jan 2011)

Log Message:
-----------
VIDEO: Implement internal-codec 16bit VMDs

Modified Paths:
--------------
    scummvm/trunk/graphics/video/coktel_decoder.cpp
    scummvm/trunk/graphics/video/coktel_decoder.h

Modified: scummvm/trunk/graphics/video/coktel_decoder.cpp
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.cpp	2011-01-16 16:29:19 UTC (rev 55262)
+++ scummvm/trunk/graphics/video/coktel_decoder.cpp	2011-01-16 16:29:43 UTC (rev 55263)
@@ -426,27 +426,27 @@
 }
 
 // A whole, completely filled block
-void CoktelDecoder::renderBlockWhole(const byte *src, Common::Rect &rect) {
+void CoktelDecoder::renderBlockWhole(Surface &dstSurf, const byte *src, Common::Rect &rect) {
 	Common::Rect srcRect = rect;
 
-	rect.clip(_surface.w, _surface.h);
+	rect.clip(dstSurf.w, dstSurf.h);
 
-	byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left * _surface.bytesPerPixel;
+	byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left * dstSurf.bytesPerPixel;
 	for (int i = 0; i < rect.height(); i++) {
-		memcpy(dst, src, rect.width() * _surface.bytesPerPixel);
+		memcpy(dst, src, rect.width() * dstSurf.bytesPerPixel);
 
-		src += srcRect.width() * _surface.bytesPerPixel;
-		dst += _surface.pitch;
+		src += srcRect.width() * dstSurf.bytesPerPixel;
+		dst += dstSurf.pitch;
 	}
 }
 
 // A quarter-wide whole, completely filled block
-void CoktelDecoder::renderBlockWhole4X(const byte *src, Common::Rect &rect) {
+void CoktelDecoder::renderBlockWhole4X(Surface &dstSurf, const byte *src, Common::Rect &rect) {
 	Common::Rect srcRect = rect;
 
-	rect.clip(_surface.w, _surface.h);
+	rect.clip(dstSurf.w, dstSurf.h);
 
-	byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+	byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
 	for (int i = 0; i < rect.height(); i++) {
 		      byte *dstRow = dst;
 		const byte *srcRow = src;
@@ -461,26 +461,26 @@
 		}
 
 		src += srcRect.width() / 4;
-		dst += _surface.pitch;
+		dst += dstSurf.pitch;
 	}
 }
 
 // A half-high whole, completely filled block
-void CoktelDecoder::renderBlockWhole2Y(const byte *src, Common::Rect &rect) {
+void CoktelDecoder::renderBlockWhole2Y(Surface &dstSurf, const byte *src, Common::Rect &rect) {
 	Common::Rect srcRect = rect;
 
-	rect.clip(_surface.w, _surface.h);
+	rect.clip(dstSurf.w, dstSurf.h);
 
 	int16 height = rect.height();
 
-	byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+	byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
 	while (height > 1) {
 		memcpy(dst                 , src, rect.width());
-		memcpy(dst + _surface.pitch, src, rect.width());
+		memcpy(dst + dstSurf.pitch, src, rect.width());
 
 		height -= 2;
 		src    += srcRect.width();
-		dst    += 2 * _surface.pitch;
+		dst    += 2 * dstSurf.pitch;
 	}
 
 	if (height == 1)
@@ -488,12 +488,12 @@
 }
 
 // A sparse block
-void CoktelDecoder::renderBlockSparse(const byte *src, Common::Rect &rect) {
+void CoktelDecoder::renderBlockSparse(Surface &dstSurf, const byte *src, Common::Rect &rect) {
 	Common::Rect srcRect = rect;
 
-	rect.clip(_surface.w, _surface.h);
+	rect.clip(dstSurf.w, dstSurf.h);
 
-	byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+	byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
 	for (int i = 0; i < rect.height(); i++) {
 		byte *dstRow = dst;
 		int16 pixWritten = 0;
@@ -518,19 +518,19 @@
 
 		}
 
-		dst += _surface.pitch;
+		dst += dstSurf.pitch;
 	}
 }
 
 // A half-high sparse block
-void CoktelDecoder::renderBlockSparse2Y(const byte *src, Common::Rect &rect) {
+void CoktelDecoder::renderBlockSparse2Y(Surface &dstSurf, const byte *src, Common::Rect &rect) {
 	warning("renderBlockSparse2Y");
 
 	Common::Rect srcRect = rect;
 
-	rect.clip(_surface.w, _surface.h);
+	rect.clip(dstSurf.w, dstSurf.h);
 
-	byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+	byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
 	for (int i = 0; i < rect.height(); i += 2) {
 		byte *dstRow = dst;
 		int16 pixWritten = 0;
@@ -544,7 +544,7 @@
 				pixCount  = MIN((pixCount & 0x7F) + 1, srcRect.width() - pixWritten);
 				copyCount = CLIP<int16>(rect.width() - pixWritten, 0, pixCount);
 				memcpy(dstRow                 , src, pixCount);
-				memcpy(dstRow + _surface.pitch, src, pixCount);
+				memcpy(dstRow + dstSurf.pitch, src, pixCount);
 
 				pixWritten += pixCount;
 				dstRow     += pixCount;
@@ -556,16 +556,16 @@
 
 		}
 
-		dst += _surface.pitch;
+		dst += dstSurf.pitch;
 	}
 }
 
-void CoktelDecoder::renderBlockRLE(const byte *src, Common::Rect &rect) {
+void CoktelDecoder::renderBlockRLE(Surface &dstSurf, const byte *src, Common::Rect &rect) {
 	Common::Rect srcRect = rect;
 
-	rect.clip(_surface.w, _surface.h);
+	rect.clip(dstSurf.w, dstSurf.h);
 
-	byte *dst = (byte *)_surface.pixels + (rect.top * _surface.pitch) + rect.left;
+	byte *dst = (byte *)dstSurf.pixels + (rect.top * dstSurf.pitch) + rect.left;
 	for (int i = 0; i < rect.height(); i++) {
 		byte *dstRow = dst;
 		int16 pixWritten = 0;
@@ -597,7 +597,7 @@
 
 		}
 
-		dst += _surface.pitch;
+		dst += dstSurf.pitch;
 	}
 }
 
@@ -1386,15 +1386,15 @@
 
 	// Evaluate the block type
 	if      (type == 0x01)
-		renderBlockSparse  (dataPtr, rect);
+		renderBlockSparse  (_surface, dataPtr, rect);
 	else if (type == 0x02)
-		renderBlockWhole   (dataPtr, rect);
+		renderBlockWhole   (_surface, dataPtr, rect);
 	else if (type == 0x42)
-		renderBlockWhole4X (dataPtr, rect);
+		renderBlockWhole4X (_surface, dataPtr, rect);
 	else if ((type & 0x0F) == 0x02)
-		renderBlockWhole2Y (dataPtr, rect);
+		renderBlockWhole2Y (_surface, dataPtr, rect);
 	else
-		renderBlockSparse2Y(dataPtr, rect);
+		renderBlockSparse2Y(_surface, dataPtr, rect);
 
 	return true;
 }
@@ -1534,8 +1534,10 @@
 
 	_videoBuffer   [0] = 0;
 	_videoBuffer   [1] = 0;
+	_videoBuffer   [2] = 0;
 	_videoBufferLen[0] = 0;
 	_videoBufferLen[1] = 0;
+	_videoBufferLen[2] = 0;
 }
 
 VMDDecoder::~VMDDecoder() {
@@ -1566,6 +1568,9 @@
 }
 
 void VMDDecoder::setXY(uint16 x, uint16 y) {
+	if (_blitMode == 1)
+		x *= _bytesPerPixel;
+
 	for (uint32 i = 0; i < _frameCount; i++) {
 		for (int j = 0; j < _partsPerFrame; j++) {
 
@@ -1756,18 +1761,13 @@
 	else if ((_bytesPerPixel == 2) || (_bytesPerPixel == 3)) {
 		int n = (_flags & 0x80) ? 2 : 3;
 
-		_blitMode      = n - 1;
+		_blitMode      = _bytesPerPixel - 1;
 		_bytesPerPixel = n;
 
 		_isPaletted = false;
 	}
 
-	if ((_bytesPerPixel > 1) && !_externalCodec) {
-		warning("VMDDecoder::assessVideoProperties(): TODO: Internal _bytesPerPixel == %d", _bytesPerPixel);
-		return false;
-	}
-
-	if (_blitMode != 0)
+	if (_blitMode == 1)
 		_width /= _bytesPerPixel;
 
 	if (_hasVideo) {
@@ -1782,9 +1782,15 @@
 			_videoBufferSize = suggestedVideoBufferSize;
 		}
 
-		for (int i = 0; i < 2; i++) {
+		for (int i = 0; i < 3; i++) {
 			_videoBuffer[i] = new byte[_videoBufferSize];
 			memset(_videoBuffer[i], 0, _videoBufferSize);
+
+			_8bppSurface[i].w             = _width * _bytesPerPixel;
+			_8bppSurface[i].h             = _height;
+			_8bppSurface[i].pitch         = _width * _bytesPerPixel;
+			_8bppSurface[i].pixels        = _videoBuffer[i];
+			_8bppSurface[i].bytesPerPixel = 1;
 		}
 	}
 
@@ -1955,6 +1961,7 @@
 
 	delete[] _videoBuffer[0];
 	delete[] _videoBuffer[1];
+	delete[] _videoBuffer[2];
 
 	delete _codec;
 
@@ -1990,8 +1997,10 @@
 	_videoBufferSize   = 0;
 	_videoBuffer   [0] = 0;
 	_videoBuffer   [1] = 0;
+	_videoBuffer   [2] = 0;
 	_videoBufferLen[0] = 0;
 	_videoBufferLen[1] = 0;
+	_videoBufferLen[2] = 0;
 
 	_externalCodec = false;
 	_codec         = 0;
@@ -2156,15 +2165,39 @@
 }
 
 bool VMDDecoder::renderFrame(Common::Rect &rect) {
-	if (!rect.isValidRect())
-		// Invalid rendering area
-		return false;
+	Common::Rect realRect = rect;
+	Common::Rect fakeRect = rect;
 
-	// Clip the rendering area to the video's visible area
-	rect.clip(Common::Rect(_x, _y, _x + _width, _y + _height));
-	if (!rect.isValidRect() || rect.isEmpty())
-		// Result is empty => nothing to do
+	if (_blitMode == 1) {
+		realRect = Common::Rect(rect.left  / _bytesPerPixel, rect.top,
+		                        rect.right / _bytesPerPixel, rect.bottom);
+
+		realRect = Common::Rect(realRect.left  - _x / _bytesPerPixel, realRect.top    - _y,
+		                        realRect.right - _x / _bytesPerPixel, realRect.bottom - _y);
+
+		fakeRect = Common::Rect(fakeRect.left  - _x, fakeRect.top    - _y,
+		                        fakeRect.right - _x, fakeRect.bottom - _y);
+	}
+
+	if (_blitMode == 2) {
+		fakeRect = Common::Rect(rect.left  * _bytesPerPixel, rect.top,
+		                        rect.right * _bytesPerPixel, rect.bottom);
+
+		realRect = Common::Rect(realRect.left  - _x, realRect.top    - _y,
+		                        realRect.right - _x, realRect.bottom - _y);
+
+		fakeRect = Common::Rect(fakeRect.left  - _x * _bytesPerPixel, fakeRect.top    - _y,
+		                        fakeRect.right - _x * _bytesPerPixel, fakeRect.bottom - _y);
+	}
+
+
+	realRect.clip(Common::Rect(_width, _height));
+	fakeRect.clip(Common::Rect(_width * _bytesPerPixel, _height));
+
+	if (!realRect.isValidRect() || realRect.isEmpty())
 		return false;
+	if (!fakeRect.isValidRect() || realRect.isEmpty())
+		return false;
 
 	if (_externalCodec) {
 		if (!_codec)
@@ -2178,19 +2211,14 @@
 		rect = Common::Rect(_x, _y, _x + codecSurf->w, _y + codecSurf->h);
 		rect.clip(Common::Rect(_x, _y, _x + _width, _y + _height));
 
-		renderBlockWhole((const byte *) codecSurf->pixels, rect);
+		renderBlockWhole(_surface, (const byte *) codecSurf->pixels, rect);
 		return true;
 	}
 
-	if (_blitMode > 0) {
-		// TODO
-		warning("_blitMode == %d", _blitMode);
-		return false;
-	}
+	uint8  srcBuffer = 0;
+	byte  *dataPtr   = _videoBuffer[srcBuffer];
+	uint32 dataSize  = _videoBufferLen[srcBuffer] - 1;
 
-	byte  *dataPtr  = _videoBuffer[0];
-	uint32 dataSize = _videoBufferLen[0] - 1;
-
 	uint8 type = *dataPtr++;
 
 	if (type & 0x80) {
@@ -2198,36 +2226,109 @@
 
 		type &= 0x7F;
 
-		if ((type == 2) && (rect.width() == _surface.w) && (_x == 0)) {
+		if ((type == 2) && (rect.width() == _surface.w) && (_x == 0) && (_blitMode == 0)) {
 			// Directly uncompress onto the video surface
 			deLZ77((byte *)_surface.pixels + (_y * _surface.pitch), dataPtr, dataSize,
 					_surface.w * _surface.h * _surface.bytesPerPixel);
 			return true;
 		}
 
-		_videoBufferLen[1] = deLZ77(_videoBuffer[1], dataPtr, dataSize, _videoBufferSize);
+		srcBuffer = 1;
+		_videoBufferLen[srcBuffer] =
+			deLZ77(_videoBuffer[srcBuffer], dataPtr, dataSize, _videoBufferSize);
 
-		dataPtr  = _videoBuffer[1];
-		dataSize = _videoBufferLen[1];
+		dataPtr  = _videoBuffer[srcBuffer];
+		dataSize = _videoBufferLen[srcBuffer];
 	}
 
+	Common::Rect *blockRect = &fakeRect;
+	Surface      *surface   = &_surface;
+	if (_blitMode == 0) {
+		*blockRect = Common::Rect(blockRect->left  + _x, blockRect->top    + _y,
+		                          blockRect->right + _x, blockRect->bottom + _y);
+	} else {
+		surface = &_8bppSurface[2];
+	}
+
 	// Evaluate the block type
 	if      (type == 0x01)
-		renderBlockSparse  (dataPtr, rect);
+		renderBlockSparse  (*surface, dataPtr, *blockRect);
 	else if (type == 0x02)
-		renderBlockWhole   (dataPtr, rect);
+		renderBlockWhole   (*surface, dataPtr, *blockRect);
 	else if (type == 0x03)
-		renderBlockRLE     (dataPtr, rect);
+		renderBlockRLE     (*surface, dataPtr, *blockRect);
 	else if (type == 0x42)
-		renderBlockWhole4X (dataPtr, rect);
+		renderBlockWhole4X (*surface, dataPtr, *blockRect);
 	else if ((type & 0x0F) == 0x02)
-		renderBlockWhole2Y (dataPtr, rect);
+		renderBlockWhole2Y (*surface, dataPtr, *blockRect);
 	else
-		renderBlockSparse2Y(dataPtr, rect);
+		renderBlockSparse2Y(*surface, dataPtr, *blockRect);
 
+	if (_blitMode > 0) {
+		if      (_bytesPerPixel == 2)
+			blit16(*surface, *blockRect);
+		else if (_bytesPerPixel == 3)
+			blit24(*surface, *blockRect);
+
+		if (_blitMode == 1)
+			*blockRect = Common::Rect(blockRect->left  + _x / _bytesPerPixel, blockRect->top    + _y,
+			                          blockRect->right + _x / _bytesPerPixel, blockRect->bottom + _y);
+		else
+			*blockRect = Common::Rect(blockRect->left  + _x, blockRect->top    + _y,
+			                          blockRect->right + _x, blockRect->bottom + _y);
+	}
+
+	rect = *blockRect;
 	return true;
 }
 
+void VMDDecoder::blit16(const Surface &srcSurf, Common::Rect &rect) {
+	rect = Common::Rect(rect.left / 2, rect.top, rect.right / 2, rect.bottom);
+
+	Common::Rect srcRect = rect;
+
+	rect.clip(_surface.w, _surface.h);
+
+	PixelFormat pixelFormat = getPixelFormat();
+
+	uint16 x = _x;
+	if (_blitMode == 1)
+		x /= 4;
+
+	const byte *src = (byte *)srcSurf.pixels +
+		(srcRect.top * srcSurf.pitch) + srcRect.left * _bytesPerPixel;
+	byte *dst = (byte *)_surface.pixels +
+		((_y + rect.top) * _surface.pitch) + (x + rect.left) * _surface.bytesPerPixel;
+
+	for (int i = 0; i < rect.height(); i++) {
+		const byte *srcRow = src;
+		      byte *dstRow = dst;
+
+		for (int j = 0; j < rect.width(); j++, srcRow += 2, dstRow += _surface.bytesPerPixel) {
+			uint16 data = READ_LE_UINT16(srcRow);
+
+			byte r = ((data & 0x7C00) >> 10) << 3;
+			byte g = ((data & 0x03E0) >>  5) << 3;
+			byte b = ((data & 0x001F) >>  0) << 3;
+
+			uint32 c = pixelFormat.RGBToColor(r, g, b);
+			if ((r == 0) && (g == 0) && (b == 0))
+				c = 0;
+
+			if (_surface.bytesPerPixel == 2)
+				*((uint16 *)dstRow) = (uint16) c;
+		}
+
+		src += srcSurf .pitch;
+		dst += _surface.pitch;
+	}
+}
+
+void VMDDecoder::blit24(const Surface &srcSurf, Common::Rect &rect) {
+	warning("TODO: blit24");
+	return;
+}
+
 void VMDDecoder::emptySoundSlice(uint32 size) {
 	byte *sound = soundEmpty(size);
 
@@ -2475,6 +2576,9 @@
 	if (_externalCodec && _codec)
 		return _codec->getPixelFormat();
 
+	if (_blitMode > 0)
+		return g_system->getScreenFormat();
+
 	return PixelFormat::createFormatCLUT8();
 }
 

Modified: scummvm/trunk/graphics/video/coktel_decoder.h
===================================================================
--- scummvm/trunk/graphics/video/coktel_decoder.h	2011-01-16 16:29:19 UTC (rev 55262)
+++ scummvm/trunk/graphics/video/coktel_decoder.h	2011-01-16 16:29:43 UTC (rev 55263)
@@ -200,12 +200,12 @@
 	void deRLE(byte *&destPtr, const byte *&srcPtr, int16 destLen, int16 srcLen);
 
 	// Block rendering
-	void renderBlockWhole   (const byte *src, Common::Rect &rect);
-	void renderBlockWhole4X (const byte *src, Common::Rect &rect);
-	void renderBlockWhole2Y (const byte *src, Common::Rect &rect);
-	void renderBlockSparse  (const byte *src, Common::Rect &rect);
-	void renderBlockSparse2Y(const byte *src, Common::Rect &rect);
-	void renderBlockRLE     (const byte *src, Common::Rect &rect);
+	void renderBlockWhole   (Surface &dstSurf, const byte *src, Common::Rect &rect);
+	void renderBlockWhole4X (Surface &dstSurf, const byte *src, Common::Rect &rect);
+	void renderBlockWhole2Y (Surface &dstSurf, const byte *src, Common::Rect &rect);
+	void renderBlockSparse  (Surface &dstSurf, const byte *src, Common::Rect &rect);
+	void renderBlockSparse2Y(Surface &dstSurf, const byte *src, Common::Rect &rect);
+	void renderBlockRLE     (Surface &dstSurf, const byte *src, Common::Rect &rect);
 
 	// Sound helper functions
 	inline void unsignedToSigned(byte *buffer, int length);
@@ -457,9 +457,11 @@
 	uint32  _firstFramePos; ///< Position of the first frame's data within the stream.
 
 	uint32 _videoBufferSize;   ///< Size of the video buffers.
-	byte  *_videoBuffer[2];    ///< Video buffers.
-	uint32 _videoBufferLen[2]; ///< Size of the video buffers filled.
+	byte  *_videoBuffer[3];    ///< Video buffers.
+	uint32 _videoBufferLen[3]; ///< Size of the video buffers filled.
 
+	Surface _8bppSurface[3]; ///< Fake 8bpp surfaces over the video buffers.
+
 	bool _externalCodec;
 	Codec *_codec;
 
@@ -479,6 +481,8 @@
 
 	// Video
 	bool renderFrame(Common::Rect &rect);
+	void blit16(const Surface &srcSurf, Common::Rect &rect);
+	void blit24(const Surface &srcSurf, Common::Rect &rect);
 
 	// Sound
 	void emptySoundSlice  (uint32 size);


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