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

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Fri Feb 4 18:52:00 CET 2011


Revision: 55772
          http://scummvm.svn.sourceforge.net/scummvm/?rev=55772&view=rev
Author:   thebluegr
Date:     2011-02-04 17:51:59 +0000 (Fri, 04 Feb 2011)

Log Message:
-----------
SCI: Rewrote the robot playing code in a way similar to other video decoders

- The code now streams videos instead of loading them in memory, without utilizing seeking
- Removed the sound-related robot code from the graphics classes
- Started implementing the code for the sound in robot videos (still not finished)

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

Modified: scummvm/trunk/engines/sci/console.cpp
===================================================================
--- scummvm/trunk/engines/sci/console.cpp	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/console.cpp	2011-02-04 17:51:59 UTC (rev 55772)
@@ -121,7 +121,6 @@
 	DCmd_Register("draw_cel",			WRAP_METHOD(Console, cmdDrawCel));
 #ifdef ENABLE_SCI32
 	DCmd_Register("draw_robot",			WRAP_METHOD(Console, cmdDrawRobot));
-	DCmd_Register("play_robot_audio",		WRAP_METHOD(Console, cmdPlayRobotAudio));
 #endif
 	DCmd_Register("undither",           WRAP_METHOD(Console, cmdUndither));
 	DCmd_Register("pic_visualize",		WRAP_METHOD(Console, cmdPicVisualize));
@@ -1529,23 +1528,6 @@
 	return true;
 }
 
-bool Console::cmdPlayRobotAudio(int argc, const char **argv) {
-	if (argc < 2) {
-		DebugPrintf("Draws frames from a robot resource\n");
-		DebugPrintf("Usage: %s <resourceId>\n", argv[0]);
-		DebugPrintf("where <resourceId> is the id of the robot resource to draw\n");
-		return true;
-	}
-
-	uint16 resourceId = atoi(argv[1]);
-
-	if (_engine->_gfxPaint32) {
-		_engine->_gfxPaint32->debugPlayRobotAudio(resourceId);
-	} else {
-		DebugPrintf("command not available in non-sci32 games");
-	}
-	return true;
-}
 #endif
 
 bool Console::cmdUndither(int argc, const char **argv) {

Modified: scummvm/trunk/engines/sci/console.h
===================================================================
--- scummvm/trunk/engines/sci/console.h	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/console.h	2011-02-04 17:51:59 UTC (rev 55772)
@@ -93,7 +93,6 @@
 	bool cmdDrawCel(int argc, const char **argv);
 #ifdef ENABLE_SCI32
 	bool cmdDrawRobot(int argc, const char **argv);
-	bool cmdPlayRobotAudio(int argc, const char **argv);
 #endif
 	bool cmdUndither(int argc, const char **argv);
 	bool cmdPicVisualize(int argc, const char **argv);

Modified: scummvm/trunk/engines/sci/engine/kgraphics.cpp
===================================================================
--- scummvm/trunk/engines/sci/engine/kgraphics.cpp	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/engine/kgraphics.cpp	2011-02-04 17:51:59 UTC (rev 55772)
@@ -1423,7 +1423,7 @@
 			warning("kRobot(%d)", subop);
 			break;
 		case 8: // sync
-			robot->drawNextFrame();
+			robot->processNextFrame();
 			// Signal the engine scripts that the video is done
 			if (robot->getCurFrame() ==  robot->getFrameCount())
 				writeSelector(s->_segMan, argv[1], SELECTOR(signal), SIGNAL_REG);

Modified: scummvm/trunk/engines/sci/graphics/paint32.cpp
===================================================================
--- scummvm/trunk/engines/sci/graphics/paint32.cpp	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/graphics/paint32.cpp	2011-02-04 17:51:59 UTC (rev 55772)
@@ -85,17 +85,9 @@
 	GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, _palette);
 	test->init(robotId, 0, 0);
 	while (test->getCurFrame() + 1 < test->getFrameCount()) {
-		test->drawNextFrame();
+		test->processNextFrame();
 	}
 	delete test;
 }
 
-void GfxPaint32::debugPlayRobotAudio(GuiResourceId robotId) {
-	GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, _palette);
-	test->init(robotId, 0, 0);
-	test->playAudio();	
-	delete test;
-}
-
-
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/graphics/paint32.h
===================================================================
--- scummvm/trunk/engines/sci/graphics/paint32.h	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/graphics/paint32.h	2011-02-04 17:51:59 UTC (rev 55772)
@@ -49,7 +49,6 @@
 	void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control);
 
 	void debugDrawRobot(GuiResourceId robotId);
-	void debugPlayRobotAudio(GuiResourceId robotId);
 
 private:
 	ResourceManager *_resMan;

Modified: scummvm/trunk/engines/sci/graphics/robot.cpp
===================================================================
--- scummvm/trunk/engines/sci/graphics/robot.cpp	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/graphics/robot.cpp	2011-02-04 17:51:59 UTC (rev 55772)
@@ -40,7 +40,8 @@
 
 #include "common/file.h"
 #include "common/system.h"
-#include "common/memstream.h"
+#include "common/stream.h"
+#include "common/substream.h"
 
 namespace Sci {
 
@@ -60,9 +61,10 @@
 // around the screen and go behind other objects. (...)
 
 #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), _outputBuffer(0), _outputBufferSize(0) {
+	: _resMan(resMan), _screen(screen), _palette(palette), _outputBuffer(0),
+	_outputBufferSize(0), _audioStream(0) {
 	_resourceId = -1;
 	_x = _y = 0;
 }
@@ -72,152 +74,92 @@
 }
 
 void GfxRobot::init(GuiResourceId resourceId, uint16 x, uint16 y) {
-	char fileName[10];
-	uint32 fileSize;
-
-	//	resourceId = 1305;	// debug
-
 	_resourceId = resourceId;
+	//_resourceId = 1305;	// debug
 	_x = x;
 	_y = y;
 	_curFrame = 0;
+
+	char fileName[10];
 	sprintf(fileName, "%d.rbt", _resourceId);
 
-	Common::File robotFile;
-	if (robotFile.open(fileName)) {
-		_resourceData = new byte[robotFile.size()];
-		robotFile.read(_resourceData, robotFile.size());
-		fileSize = robotFile.size();
-		robotFile.close();
-	} else {
+	if (!_robotFile.open(fileName)) {
 		warning("Unable to open robot file %s", fileName);
 		return;
 	}
 
+	readHeaderChunk();
+
 	// There are several versions of robot files, ranging from 3 to 6.
 	// v3: no known examples
 	// v4: PQ:SWAT
 	// v5: SCI2.1 and SCI3 games
 	// v6: SCI3 games
-	_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
-	// equals this value plus 14 (audio header size) in the cases
-	// I've seen so far. Dunno which one to use, really.
-	_audioSize = READ_LE_UINT16(_resourceData + 60);
-
-	//_frameSize = READ_LE_UINT32(_resourceData + 34);
-	_hasSound = (_resourceData[25] != 0);
-
-	_palOffset = 60;
-
-	// Some robot files have sound, which doesn't start from frame 0
-	// (e.g. Phantasmagoria, robot 1305)
-	// Yes, strangely, the word at offset 10 is non-zero if it DOESN'T have a preload
-	// in that case, the word is equal to that value which would otherwise be stored
-	// in the audio header (i.e. _audioSize above)
-	if (_hasSound && READ_LE_UINT16(_resourceData + 10) == 0)
-		_palOffset += READ_LE_UINT32(_resourceData + 60) + 14;
-
-	switch (_version) {
-	case 3:
-		// Unsupported, and there doesn't seem to be any game that actually
-		// uses this, thus error out so that we find out where this is used
-		error("Unknown robot version: %d", _version);
-		break;
+	switch (_header.version) {
 	case 4:	// used in PQ:SWAT
 		// Unsupported
-		// TODO: Add support for this version
 		warning("TODO: add support for v4 robot videos");
-		_curFrame = _frameCount;	// jump to the last frame
+		_curFrame = _header.frameCount;	// jump to the last frame
 		return;
-	case 5:	// used in most SCI2.1 games
+	case 5:	// used in most SCI2.1 games and in some SCI3 robots
+	case 6:	// used in SCI3 games
 		// Supported
 		break;
-	case 6:	// introduced in SCI3
-		// Unsupported
-		// TODO: Add support for this version
-		warning("TODO: add support for v6 robot videos");
-		break;
 	default:
 		// Unsupported, error out so that we find out where this is used
-		error("Unknown robot version: %d", _version);
+		error("Unknown robot version: %d", _header.version);
 	}
 
-	getFrameOffsets();
-	assert(_imageStart[_frameCount] == fileSize);
+	_frameTotalSize = new uint32[_header.frameCount];
+#if 0
+	if (_header.hasSound) {
+		_audioStream = Audio::makeQueuingAudioStream(22050, true);
+		g_system->getMixer()->playStream(Audio::Mixer::kMusicSoundType, &_audioHandle, _audioStream);
+	}
+#endif
 
-	setPalette();
+	readPaletteChunk();
+	readFrameSizesChunk();
 
-	debug("Robot %d, %d frames, sound: %s\n", resourceId, _frameCount, _hasSound ? "yes" : "no");
+	debug("Robot %d, %d frames, sound: %s\n", resourceId, _header.frameCount, _header.hasSound ? "yes" : "no");
 }
 
-void GfxRobot::getFrameOffsets() {
-	int *audioEnd = new int[_frameCount];
-	int *videoEnd = new int[_frameCount];
-	uint32 frameDataOffset;
+void GfxRobot::readHeaderChunk() {
+	// Header (60 bytes)
+	_robotFile.skip(6);
+	_header.version = _robotFile.readUint16LE();
+	_robotFile.skip(2);
+	_header.audioSilenceSize = _robotFile.readUint16LE();
+	_robotFile.skip(2);
+	_header.frameCount = _robotFile.readUint16LE();
+	_header.paletteDataSize = _robotFile.readUint16LE();
+	_robotFile.skip(7);
+	_header.hasSound = _robotFile.readByte();
+	_robotFile.skip(34);
 
-	switch (_version) {
-	case 5:
-		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);
-		}
- 		frameDataOffset = _palOffset + 0x4b0 + 0x400 + 0x200 + _frameCount * 4;
-		break;
-	case 6:
-		for (int i = 0; i < _frameCount; ++i) {
-			videoEnd[i] = READ_LE_UINT32(_resourceData + _palOffset + 1200 + i * 4);
-			audioEnd[i] = READ_LE_UINT32(_resourceData + _palOffset + 1200 + _frameCount * 4 + i * 4);
-		}
- 		frameDataOffset = _palOffset + 0x4b0 + 0x400 + 0x200 + _frameCount * 8;
-		break;
-	default:
-		error("Can't yet handle index table for robot version %d", _version);
-		return;
+	// Some robot files have sound, which doesn't start from frame 0
+	// (e.g. Phantasmagoria, robot 1305). In this case, there won't
+	// be audio silence in the header, but there will be an extra audio
+	// preload chunk before the palette chunk. Skip past it and its 
+	// 14-byte header.
+	if (_header.hasSound && !_header.audioSilenceSize) {
+		// The header is 14 bytes: the chunk size + 10 more
+		uint32 preloadChunkSize = _robotFile.readUint32LE();
+		_robotFile.skip(preloadChunkSize + 10);
 	}
-
-	
-	// 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);
-
+void GfxRobot::readPaletteChunk() {
+	byte *paletteChunk = new byte[_header.paletteDataSize];
+	_robotFile.read(paletteChunk, _header.paletteDataSize);
+	int startIndex = READ_LE_UINT16(paletteChunk + 25);
+	int colorCount = READ_LE_UINT16(paletteChunk + 29);
 	Palette resourcePal;
+	_palette->createFromData(paletteChunk, _header.paletteDataSize, &resourcePal);
+	delete[] paletteChunk;
 
 	byte robotPal[256 * 4];
-	int startIndex = READ_LE_UINT16(paletteData + 25);
-	int colorCount = READ_LE_UINT16(paletteData + 29);
 
-	warning("%d palette entries starting at %d", colorCount, startIndex);
-	
-	_palette->createFromData(paletteData, paletteSize, &resourcePal);
-
 	for (int i = 0; i < 256; ++i) {
 		_savedPal[i * 4 + 0] = _palette->_sysPalette.colors[i].r;
 		_savedPal[i * 4 + 1] = _palette->_sysPalette.colors[i].g;
@@ -238,134 +180,124 @@
 	g_system->setPalette(robotPal, 0, 256);
 }
 
-void GfxRobot::drawNextFrame() {
-	uint16 width, height;
 
-	// Make sure that we haven't reached the end of the video already
-	if (_curFrame == _frameCount)
-		return;
+void GfxRobot::readFrameSizesChunk() {
+	switch (_header.version) {
+	case 5:		// sizes are 16-bit integers
+		// Skip table with frame image sizes, as we don't need it
+		_robotFile.skip(_header.frameCount * 2);
+		for (int i = 0; i < _header.frameCount; ++i)
+			_frameTotalSize[i] = _robotFile.readUint16LE();
+		break;
+	case 6:		// sizes are 32-bit integers
+		// Skip table with frame image sizes, as we don't need it
+		_robotFile.skip(_header.frameCount * 4);
+		for (int i = 0; i < _header.frameCount; ++i)
+			_frameTotalSize[i] = _robotFile.readUint32LE();
+		break;
+	default:
+		error("Can't yet handle index table for robot version %d", _header.version);
+	}
 
-	assembleVideoFrame(_curFrame);
-	getFrameDimensions(_curFrame, width, height);
-	
-	g_system->copyRectToScreen(_outputBuffer, width, _x, _y, width, height * getFrameScale(_curFrame) / 100);
-	g_system->updateScreen();
-	g_system->delayMillis(100);
+	_robotFile.skip(1024 + 512);	// Skip unknown tables 1 and 2
 
-	_curFrame++;
-
-	if (_curFrame == _frameCount) {
-		// End of robot video, restore palette
-		g_system->setPalette(_savedPal, 0, 256);
-		_resourceId = -1;
-		freeData();
+	// Pad to nearest 2 kilobytes
+	uint32 curPos = _robotFile.pos();
+	if (curPos & 0x7ff) {
+		curPos = (curPos & ~0x7ff) + 2048;
+		_robotFile.seek(curPos);
 	}
 }
 
-void GfxRobot::assembleVideoFrame(uint16 frame) {
-	byte *videoData = _resourceData + _imageStart[frame];
-	uint16 frameFragments = READ_LE_UINT16(videoData + 18);
+void GfxRobot::processNextFrame() {
+	// Make sure that we haven't reached the end of the video already
+	if (_curFrame == _header.frameCount)
+		return;
 
-	uint32 decompressedSize = 0;
+	// Read frame header (24 bytes)
+	_robotFile.skip(3);
+	byte frameScale = _robotFile.readByte();
+	uint16 frameWidth = _robotFile.readUint16LE();
+	uint16 frameHeight = _robotFile.readUint16LE();
+	_robotFile.skip(8);		// x, y, width and height of the frame
+	uint16 compressedSize = _robotFile.readUint16LE();
+	uint16 frameFragments = _robotFile.readUint16LE();
+	_robotFile.skip(4);		// unknown
 
-	DecompressorLZS lzs;
+	uint32 decompressedSize = frameWidth * (frameHeight * frameScale / 100);
 
-	videoData = _resourceData + _imageStart[frame] + 24;
-	
-	for (int i = 0; i < frameFragments; ++i) {
-		uint32 fragmentCompressed = READ_LE_UINT32(videoData);
-		uint32 fragmentUncompressed = READ_LE_UINT32(videoData + 4);
-
-		decompressedSize += fragmentUncompressed;
-		videoData += 10 + fragmentCompressed;
-	}
-
-	// Causes assertions in various places, such as Lighthouse/Demo 693.RBT
-	// uint16 frameWidth = READ_LE_UINT16(_resourceData + _imageStart[frame] + 4);
-	// uint16 frameHeight = READ_LE_UINT16(_resourceData + _imageStart[frame] + 6);
-	// assert(decompressedSize == (uint32)(frameWidth * frameHeight) * getFrameScale(frame) / 100);
-	
-	// Reallocate the output buffer, if its size has changed
-	if (decompressedSize != _outputBufferSize) {
+	// Reallocate the output buffer, if its size has increased
+	if (decompressedSize > _outputBufferSize) {
 		delete[] _outputBuffer;
 		_outputBuffer = new byte[decompressedSize];
 	}
-
+	
 	_outputBufferSize = decompressedSize;
 
-	uint32 assemblePtr = 0;
+	DecompressorLZS lzs;
+	byte *outPtr = _outputBuffer;
 
-	videoData = _resourceData + _imageStart[frame] + 24;
+	for (uint16 i = 0; i < frameFragments; ++i) {
+		uint32 compressedFragmentSize = _robotFile.readUint32LE();
+		uint32 decompressedFragmentSize = _robotFile.readUint32LE();
+		uint16 compressionType = _robotFile.readUint16LE();
 
-	for (int i = 0; i < frameFragments; ++i) {
-		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, _outputBuffer + assemblePtr, fragmentCompressed, fragmentUncompressed);
-			assemblePtr += fragmentUncompressed;
-			break;
+		if (compressionType == 0) {
+			Common::SeekableSubReadStream fragmentStream(&_robotFile, _robotFile.pos(), _robotFile.pos() + compressedFragmentSize);
+			lzs.unpack(&fragmentStream, outPtr, compressedFragmentSize, decompressedFragmentSize);
+		} else if (compressionType == 2) {	// untested
+			_robotFile.read(outPtr, compressedFragmentSize);
+		} else {
+			error("Unknown frame compression found: %d", compressionType);
 		}
-		case 2: // Untested
-			memcpy(_outputBuffer + assemblePtr, videoData + 10, fragmentCompressed);
-			assemblePtr += fragmentUncompressed;
-			break;
-		}
-		
-		videoData += 10 + fragmentCompressed;
+
+		outPtr += decompressedFragmentSize;
 	}
 
-	assert(assemblePtr == decompressedSize);
+	uint32 audioChunkSize = _frameTotalSize[_curFrame] - (24 + compressedSize);
 
-	//	FILE *f = fopen("/tmp/flap", "w");
-	//      fwrite(_outputBuffer, 1, decompressedSize, f);
-	//      fclose(f);
-	//      exit(1);
-}
-
-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);
-}
-
+	// TODO: Audio
 #if 0
-Common::Rect GfxRobot::getFrameRect(uint16 frame) {
-	byte *videoData = _resourceData + _imageStart[frame];
+	// Queue the next audio frame
+	if (_header.hasSound) {
+		uint16 decodedSize = _robotFile.readUint16LE();
+		_robotFile.skip(2);	// skip audio buffer position
 
-	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);
-
-	return Common::Rect(x, y, x + w, y + h); 
-}
+		byte *audioFrame = g_sci->_audio->getDecodedRobotAudioFrame(&_robotFile, audioChunkSize - 4);
+		_audioStream->queueBuffer(audioFrame, decodedSize, DisposeAfterUse::NO, Audio::FLAG_LITTLE_ENDIAN | Audio::FLAG_STEREO);
+	} else {
+		_robotFile.skip(audioChunkSize);
+	}
+#else
+	_robotFile.skip(audioChunkSize);
 #endif
 
-byte GfxRobot::getFrameScale(uint16 frame) {
-	byte *videoData = _resourceData + _imageStart[frame];
-	return videoData[3];
-}
+	// Show frame
+	g_system->copyRectToScreen(_outputBuffer, frameWidth, _x, _y, frameWidth, frameHeight * frameScale / 100);
+	g_system->updateScreen();
+	g_system->delayMillis(100);
 
-void GfxRobot::playAudio() {
-	if (_hasSound) {
-		Audio::SoundHandle _audioHandle;
-		Audio::AudioStream *audioStream = g_sci->_audio->getRobotAudioStream(_resourceData);
-		g_system->getMixer()->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream);
+	_curFrame++;
+
+	if (_curFrame == _header.frameCount) {
+		// End of robot video, restore palette
+		g_system->setPalette(_savedPal, 0, 256);
+		_resourceId = -1;
+		freeData();
 	}
 }
 
 void GfxRobot::freeData() {
-	delete[] _resourceData; _resourceData = 0;
-	delete[] _imageStart; _imageStart = 0;
-	delete[] _audioStart; _audioStart = 0;
-	delete[] _audioLen; _audioLen = 0;
+#if 0
+	if (_header.hasSound) {
+		g_system->getMixer()->stopHandle(_audioHandle);
+		//delete _audioStream; _audioStream = 0;
+	}
+#endif
+	delete[] _frameTotalSize; _frameTotalSize = 0;
 	delete[] _outputBuffer; _outputBuffer = 0;
+	_outputBufferSize = 0;
+	_robotFile.close();
 }	
 
 #endif

Modified: scummvm/trunk/engines/sci/graphics/robot.h
===================================================================
--- scummvm/trunk/engines/sci/graphics/robot.h	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/graphics/robot.h	2011-02-04 17:51:59 UTC (rev 55772)
@@ -26,34 +26,46 @@
 #ifndef SCI_GRAPHICS_ROBOT_H
 #define SCI_GRAPHICS_ROBOT_H
 
+#include "common/file.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+#include "sound/decoders/raw.h"
+
 namespace Sci {
 
-#define ROBOT_FILE_STARTOFDATA 58
+#ifdef ENABLE_SCI32
 
-#ifdef ENABLE_SCI32
+struct RobotHeader {
+	// 6 bytes, identifier bytes
+	uint16 version;
+	// 2 bytes, unknown
+	uint16 audioSilenceSize;
+	// 2 bytes, unknown
+	uint16 frameCount;
+	uint16 paletteDataSize;
+	// 6 bytes, unknown
+	byte hasSound;
+	// 35 bytes, unknown
+};
+
 class GfxRobot {
 public:
 	GfxRobot(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette);
 	~GfxRobot();
 
 	void init(GuiResourceId resourceId, uint16 x, uint16 y);
-	void drawNextFrame();
+	void processNextFrame();
 	uint16 getCurFrame() { return _curFrame; }
-	uint16 getFrameCount() { return _frameCount; }
+	uint16 getFrameCount() { return _header.frameCount; }
 	bool isPlaying() { return _resourceId != -1; }
 	void playAudio();
 
 private:
-	void initData(GuiResourceId resourceId);
-	void getFrameOffsets();
-	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 readHeaderChunk();
+	void readPaletteChunk();
+	void readFrameSizesChunk();
+
 	void freeData();
 
 	ResourceManager *_resMan;
@@ -61,23 +73,18 @@
 	GfxPalette *_palette;
 
 	GuiResourceId _resourceId;
-	byte *_resourceData;
 	byte _savedPal[256 * 4];
 
-	byte _version;	// robot version
+	Common::File _robotFile;
+	Audio::QueuingAudioStream *_audioStream;
+	Audio::SoundHandle _audioHandle;
+
+	RobotHeader _header;
+
 	uint16 _x;
 	uint16 _y;
-	//uint16 _width;
-	//uint16 _height;
-	uint16 _frameCount;
-	uint32 _frameSize; // is width * height (pixelCount)
-	uint16 _audioSize;
-	bool _hasSound;
-	uint32 _palOffset;
-	uint32 *_imageStart;
-	uint32 *_audioStart;
-	uint32 *_audioLen;
 	uint16 _curFrame;
+	uint32 *_frameTotalSize;
 
 	byte *_outputBuffer;
 	uint32 _outputBufferSize;

Modified: scummvm/trunk/engines/sci/sound/audio.cpp
===================================================================
--- scummvm/trunk/engines/sci/sound/audio.cpp	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/sound/audio.cpp	2011-02-04 17:51:59 UTC (rev 55772)
@@ -243,18 +243,9 @@
 	return buffer;
 }
 
-// FIXME: This doesn't work correctly yet, perhaps there are differences in the
-// way the audio in robot files is handled
-Audio::RewindableAudioStream *AudioPlayer::getRobotAudioStream(byte *buffer) {
-	const uint16 rbtHeaderSize = 19;	// TODO: is this right?
-	const uint16 rbtAudioRate = 22050;	// Seems to be hardcoded for all Robot videos
-	byte audioFlags = *(buffer + 6);
+byte *AudioPlayer::getDecodedRobotAudioFrame(Common::SeekableReadStream *str, uint32 encodedSize) {
 	byte flags = 0;
-	uint32 audioSize = READ_LE_UINT16(buffer + 15) - rbtHeaderSize;
-
-	Common::MemoryReadStream dataStream(buffer + rbtHeaderSize - 1, audioSize, DisposeAfterUse::NO);
-	byte *data = readSOLAudio(&dataStream, audioSize, audioFlags, flags);
-	return Audio::makeRawStream(data, audioSize, rbtAudioRate, flags);
+	return readSOLAudio(str, encodedSize, 0, flags);
 }
 
 Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 volume, int *sampleLen) {

Modified: scummvm/trunk/engines/sci/sound/audio.h
===================================================================
--- scummvm/trunk/engines/sci/sound/audio.h	2011-02-04 16:16:07 UTC (rev 55771)
+++ scummvm/trunk/engines/sci/sound/audio.h	2011-02-04 17:51:59 UTC (rev 55772)
@@ -69,8 +69,8 @@
 
 	void setAudioRate(uint16 rate) { _audioRate = rate; }
 	Audio::SoundHandle *getAudioHandle() { return &_audioHandle; }
-	Audio::RewindableAudioStream *getRobotAudioStream(byte *buffer);
 	Audio::RewindableAudioStream *getAudioStream(uint32 number, uint32 volume, int *sampleLen);
+	byte *getDecodedRobotAudioFrame(Common::SeekableReadStream *str, uint32 encodedSize);
 	int getAudioPosition();
 	int startAudio(uint16 module, uint32 tuple);
 	int wPlayAudio(uint16 module, uint32 tuple);


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