[Scummvm-cvs-logs] SF.net SVN: scummvm:[35997] scummvm/trunk/engines/made

john_doe at users.sourceforge.net john_doe at users.sourceforge.net
Thu Jan 22 14:04:29 CET 2009


Revision: 35997
          http://scummvm.svn.sourceforge.net/scummvm/?rev=35997&view=rev
Author:   john_doe
Date:     2009-01-22 13:04:29 +0000 (Thu, 22 Jan 2009)

Log Message:
-----------
- Added support for The Manhole EGA version
- Support for 'chunked' picture resources and EGA pictures
- Improved the mouth sync in RtZ (still not perfect, though)
- Removed obsolete TODOs
- Fixed sfPlayMovie to return if the movie playback was aborted or not; this is used by RtZ to determine if it should display the credits screen after the intro movie

Modified Paths:
--------------
    scummvm/trunk/engines/made/database.cpp
    scummvm/trunk/engines/made/database.h
    scummvm/trunk/engines/made/detection.cpp
    scummvm/trunk/engines/made/graphics.cpp
    scummvm/trunk/engines/made/graphics.h
    scummvm/trunk/engines/made/pmvplayer.cpp
    scummvm/trunk/engines/made/pmvplayer.h
    scummvm/trunk/engines/made/resource.cpp
    scummvm/trunk/engines/made/resource.h
    scummvm/trunk/engines/made/screen.cpp
    scummvm/trunk/engines/made/scriptfuncs.cpp
    scummvm/trunk/engines/made/sound.cpp

Modified: scummvm/trunk/engines/made/database.cpp
===================================================================
--- scummvm/trunk/engines/made/database.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/database.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -179,6 +179,13 @@
 	return _objData + 4;
 }
 
+int ObjectV1::load(Common::SeekableReadStream &source) {
+	ObjectV2::load(source);
+	// Manhole EGA has the two property counts reversed
+	SWAP(_objData[2], _objData[3]);
+	return _objSize;
+}
+
 int ObjectV3::load(Common::SeekableReadStream &source) {
 
 	_freeData = true;
@@ -382,24 +389,38 @@
 	if (strncmp(header, "ADVSYS", 6))
 		warning ("Unexpected database header, expected ADVSYS");
 
-	/*uint32 unk = */sourceS.readUint16LE();
+	uint32 textOffs, objectsOffs, objectsSize, textSize;
+	uint16 objectCount, varObjectCount;
 
-	sourceS.skip(18);
+	sourceS.readUint16LE(); // skip sub-version
+	sourceS.skip(18); // skip program name
 
-	uint32 textOffs = sourceS.readUint16LE() * 512;
-	uint16 objectCount = sourceS.readUint16LE();
-	uint16 varObjectCount = sourceS.readUint16LE();
-	_gameStateSize = sourceS.readUint16LE() * 2;
-	sourceS.readUint16LE(); // unknown
-	uint32 objectsOffs = sourceS.readUint16LE() * 512;
-	sourceS.readUint16LE(); // unknown
-	_mainCodeObjectIndex = sourceS.readUint16LE();
-	sourceS.readUint16LE(); // unknown
-	uint32 objectsSize = sourceS.readUint32LE() * 2;
-	uint32 textSize = objectsOffs - textOffs;
+	if (version == 40) {
+		sourceS.readUint16LE(); // skip unused
+		objectCount = sourceS.readUint16LE();
+		_gameStateSize = sourceS.readUint16LE() * 2;
+		objectsOffs = sourceS.readUint16LE() * 512;
+		textOffs = sourceS.readUint16LE() * 512;
+		_mainCodeObjectIndex = sourceS.readUint16LE();
+		varObjectCount = 0; // unused in V1
+		objectsSize = 0; // unused in V1
+	} else if (version == 54) {
+		textOffs = sourceS.readUint16LE() * 512;
+		objectCount = sourceS.readUint16LE();
+		varObjectCount = sourceS.readUint16LE();
+		_gameStateSize = sourceS.readUint16LE() * 2;
+		sourceS.readUint16LE(); // unknown
+		objectsOffs = sourceS.readUint16LE() * 512;
+		sourceS.readUint16LE(); // unknown
+		_mainCodeObjectIndex = sourceS.readUint16LE();
+		sourceS.readUint16LE(); // unknown
+		objectsSize = sourceS.readUint32LE() * 2;
+	}
 
-	debug(2, "textOffs = %08X; textSize = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", textOffs, textSize, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize);
+	textSize = objectsOffs - textOffs;
 
+	debug(0, "textOffs = %08X; textSize = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d; _mainCodeObjectIndex = %04X\n", textOffs, textSize, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize, _mainCodeObjectIndex);
+
 	_gameState = new byte[_gameStateSize + 2];
 	memset(_gameState, 0, _gameStateSize + 2);
 	setVar(1, objectCount);
@@ -410,15 +431,35 @@
 	// "Decrypt" the text data
 	for (uint32 i = 0; i < textSize; i++)
 		_gameText[i] += 0x1E;
-
+		
 	sourceS.seek(objectsOffs);
 
-	for (uint32 i = 0; i < objectCount; i++) {
-		Object *obj = new ObjectV2();
-		int objSize = obj->load(sourceS);
-		// objects are aligned on 2-byte-boundaries, skip unused bytes
-		sourceS.skip(objSize % 2);
-		_objects.push_back(obj);
+	if (version == 40) {
+		// Initialize the object array
+		for (uint32 i = 0; i < objectCount; i++)
+			_objects.push_back(NULL);
+		// Read two "sections" of objects
+		// It seems the first section is data while the second one is code.
+		// The interpreter however doesn't care which section the objects come from.
+		for (int section = 0; section < 2; section++) {
+			while (!sourceS.eos()) {
+				int16 objIndex = sourceS.readUint16LE();
+				debug("objIndex = %04X; section = %d", objIndex, section);
+				if (objIndex == 0)
+					break;
+				Object *obj = new ObjectV1();
+				obj->load(sourceS);
+				_objects[objIndex - 1] = obj;
+			}
+		}
+	} else if (version == 54) {
+		for (uint32 i = 0; i < objectCount; i++) {
+			Object *obj = new ObjectV2();
+			int objSize = obj->load(sourceS);
+			// Objects are aligned on 2-byte-boundaries, skip unused bytes
+			sourceS.skip(objSize % 2);
+			_objects.push_back(obj);
+		}
 	}
 
 }
@@ -464,7 +505,11 @@
 }
 
 int16 *GameDatabaseV2::findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
+
 	Object *obj = getObject(objectIndex);
+	if (obj->getClass() >= 0x7FFE) {
+		error("GameDatabaseV2::findObjectProperty(%04X, %04X) Not an object", objectIndex, propertyId);
+	}
 
 	int16 *prop = (int16*)obj->getData();
 	byte count1 = obj->getCount1();
@@ -568,11 +613,9 @@
 
 	for (uint32 i = 0; i < objectCount; i++) {
 		Object *obj = new ObjectV3();
-
 		// The LSB indicates if it's a constant or variable object.
 		// Constant objects are loaded from disk, while variable objects exist
 		// in the _gameState buffer.
-
 		if (objectOffsets[i] & 1) {
 			sourceS.seek(objectsOffs + objectOffsets[i] - 1);
 			obj->load(sourceS);
@@ -682,6 +725,9 @@
 
 int16 *GameDatabaseV3::findObjectProperty(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
 	Object *obj = getObject(objectIndex);
+	if (obj->getClass() >= 0x7FFE) {
+		error("GameDatabaseV2::findObjectProperty(%04X, %04X) Not an object", objectIndex, propertyId);
+	}
 
 	int16 *prop = (int16*)obj->getData();
 	byte count1 = obj->getCount1();

Modified: scummvm/trunk/engines/made/database.h
===================================================================
--- scummvm/trunk/engines/made/database.h	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/database.h	2009-01-22 13:04:29 UTC (rev 35997)
@@ -39,6 +39,7 @@
 
 class Object {
 public:
+
 	Object();
 	virtual ~Object();
 
@@ -86,7 +87,11 @@
 	bool isConstant() {
 		return false;
 	}
+};
 
+class ObjectV1 : public ObjectV2 {
+public:
+	int load(Common::SeekableReadStream &source);
 };
 
 class ObjectV3 : public Object {

Modified: scummvm/trunk/engines/made/detection.cpp
===================================================================
--- scummvm/trunk/engines/made/detection.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/detection.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -261,7 +261,6 @@
 		2,
 	},
 
-#if 0
 	{
 		// The Manhole (EGA, 5.25")
 		{
@@ -277,7 +276,6 @@
 		GF_FLOPPY,
 		1,
  	},
-#endif
 
 	{
 		// Leather Goddesses of Phobos 2

Modified: scummvm/trunk/engines/made/graphics.cpp
===================================================================
--- scummvm/trunk/engines/made/graphics.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/graphics.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -46,6 +46,22 @@
 	return value;
 }
 
+uint16 ValueReader::readUint16() {
+	uint16 value = READ_LE_UINT16(_buffer);
+	_buffer += 2;
+	return value;
+}
+
+uint32 ValueReader::readUint32() {
+	uint32 value = READ_LE_UINT32(_buffer);
+	_buffer += 4;
+	return value;
+}
+
+void ValueReader::resetNibbleSwitch() {
+	_nibbleSwitch = false;
+}
+
 void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, byte cmdFlags, byte pixelFlags, byte maskFlags, bool deltaFrame) {
 
 	const int offsets[] = {
@@ -59,8 +75,11 @@
 	uint16 height = surface.h;
 
 	byte *cmdBuffer = source + cmdOffs;
-	byte *maskBuffer = source + maskOffs;
+	ValueReader maskReader(source + maskOffs, (maskFlags & 2) != 0);
 	ValueReader pixelReader(source + pixelOffs, (pixelFlags & 2) != 0);
+	
+	if ((maskFlags != 0) && (maskFlags != 2) && (pixelFlags != 0) && (pixelFlags != 2) && (cmdFlags != 0))
+		error("decompressImage() Unsupported flags: cmdFlags = %02X; maskFlags = %02X, pixelFlags = %02X", cmdFlags, maskFlags, pixelFlags);
 
 	byte *destPtr = (byte*)surface.getBasePtr(0, 0);
 
@@ -109,8 +128,7 @@
 				case 1:
 					pixels[0] = pixelReader.readPixel();
 					pixels[1] = pixelReader.readPixel();
-					mask = READ_LE_UINT16(maskBuffer);
-					maskBuffer += 2;
+					mask = maskReader.readUint16();
 					for (int i = 0; i < 16; i++) {
 						lineBuf[drawDestOfs + offsets[i]] = pixels[mask & 1];
 						mask >>= 1;
@@ -122,8 +140,7 @@
 					pixels[1] = pixelReader.readPixel();
 					pixels[2] = pixelReader.readPixel();
 					pixels[3] = pixelReader.readPixel();
-					mask = READ_LE_UINT32(maskBuffer);
-					maskBuffer += 4;
+					mask = maskReader.readUint32();
 					for (int i = 0; i < 16; i++) {
 						lineBuf[drawDestOfs + offsets[i]] = pixels[mask & 3];
 						mask >>= 2;
@@ -132,9 +149,11 @@
 
 				case 3:
 					if (!deltaFrame) {
-						// Yes, it reads from maskBuffer here
+						// For EGA pictures: Pixels are read starting from a new byte
+						maskReader.resetNibbleSwitch();
+						// Yes, it reads from maskReader here
 						for (int i = 0; i < 16; i++)
-							lineBuf[drawDestOfs + offsets[i]] = *maskBuffer++;
+							lineBuf[drawDestOfs + offsets[i]] = maskReader.readPixel();
 					}
 					break;
 

Modified: scummvm/trunk/engines/made/graphics.h
===================================================================
--- scummvm/trunk/engines/made/graphics.h	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/graphics.h	2009-01-22 13:04:29 UTC (rev 35997)
@@ -37,6 +37,9 @@
 public:
 	ValueReader(byte *source, bool nibbleMode) : _buffer(source), _nibbleBuf(0), _nibbleMode(nibbleMode), _nibbleSwitch(false) {}
 	byte readPixel();
+	uint16 readUint16();
+	uint32 readUint32();
+	void resetNibbleSwitch();
 protected:
 	byte _nibbleBuf;
 	bool _nibbleMode, _nibbleSwitch;

Modified: scummvm/trunk/engines/made/pmvplayer.cpp
===================================================================
--- scummvm/trunk/engines/made/pmvplayer.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/pmvplayer.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -34,15 +34,15 @@
 PmvPlayer::~PmvPlayer() {
 }
 
-void PmvPlayer::play(const char *filename) {
+bool PmvPlayer::play(const char *filename) {
 
-	_abort = false;
+	_aborted = false;
 	_surface = NULL;
 
 	_fd = new Common::File();
 	if (!_fd->open(filename)) {
 		delete _fd;
-		return;
+		return false;
 	}
 
 	uint32 chunkType, chunkSize;
@@ -51,14 +51,14 @@
 	if (chunkType != MKID_BE('MOVE')) {
 		warning("Unexpected PMV video header, expected 'MOVE'");
 		delete _fd;
-		return;
+		return false;
 	}
 
 	readChunk(chunkType, chunkSize);	// "MHED"
 	if (chunkType != MKID_BE('MHED')) {
 		warning("Unexpected PMV video header, expected 'MHED'");
 		delete _fd;
-		return;
+		return false;
 	}
 
 	uint frameDelay = _fd->readUint16LE();
@@ -108,7 +108,7 @@
 	// get it to work well?
 	_audioStream = Audio::makeAppendableAudioStream(soundFreq, Audio::Mixer::FLAG_UNSIGNED);
 
-	while (!_vm->shouldQuit() && !_abort && !_fd->eos()) {
+	while (!_vm->shouldQuit() && !_aborted && !_fd->eos()) {
 
 		int32 frameTime = _vm->_system->getMillis();
 
@@ -208,6 +208,8 @@
 	delete _fd;
 	delete _surface;
 
+	return !_aborted;
+
 }
 
 void PmvPlayer::readChunk(uint32 &chunkType, uint32 &chunkSize) {
@@ -227,7 +229,7 @@
 		switch (event.type) {
 		case Common::EVENT_KEYDOWN:
 			if (event.kbd.keycode == Common::KEYCODE_ESCAPE)
-				_abort = true;
+				_aborted = true;
 			break;
 		default:
 			break;

Modified: scummvm/trunk/engines/made/pmvplayer.h
===================================================================
--- scummvm/trunk/engines/made/pmvplayer.h	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/pmvplayer.h	2009-01-22 13:04:29 UTC (rev 35997)
@@ -44,7 +44,8 @@
 public:
 	PmvPlayer(MadeEngine *vm, Audio::Mixer *mixer);
 	~PmvPlayer();
-	void play(const char *filename);
+	// Returns true if the movie was played till the end
+	bool play(const char *filename);
 protected:
 	MadeEngine *_vm;
 	Audio::Mixer *_mixer;
@@ -53,7 +54,7 @@
 	Audio::SoundHandle _audioStreamHandle;
 	byte _paletteRGB[768];
 	Graphics::Surface *_surface;
-	bool _abort;
+	bool _aborted;
 	void readChunk(uint32 &chunkType, uint32 &chunkSize);
 	void handleEvents();
 	void updateScreen();

Modified: scummvm/trunk/engines/made/resource.cpp
===================================================================
--- scummvm/trunk/engines/made/resource.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/resource.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -55,7 +55,16 @@
 }
 
 void PictureResource::load(byte *source, int size) {
+	if (READ_BE_UINT32(source) == MKID_BE('Flex')) {
+		loadChunked(source, size);
+	} else {
+		loadRaw(source, size);
+	}
+}
 
+void PictureResource::loadRaw(byte *source, int size) {
+	// Loads a "raw" picture as used in RtZ, LGoP2, Manhole:N&E and Rodney's Funscreen
+	
 	Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
 
 	_hasPalette = (sourceS->readByte() != 0);
@@ -71,7 +80,7 @@
 	uint16 height = sourceS->readUint16LE();
 
 	if (cmdFlags || pixelFlags || maskFlags) {
-		warning("PictureResource::load() Graphic has flags set");
+		warning("PictureResource::loadRaw() Graphic has flags set (%d, %d, %d)", cmdFlags, pixelFlags, maskFlags);
 	}
 
 	_paletteColorCount = (cmdOffs - 18) / 3; // 18 = sizeof header
@@ -92,6 +101,84 @@
 
 }
 
+void PictureResource::loadChunked(byte *source, int size) {
+	// Loads a "chunked" picture as used in Manhole EGA
+
+	Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
+
+	byte cmdFlags, pixelFlags, maskFlags;
+	uint16 cmdOffs = 0, pixelOffs = 0, maskOffs = 0;
+	uint16 lineSize = 0, width = 0, height = 0;
+
+	sourceS->skip(36); // skip the "Flex" header
+
+	_hasPalette = false;
+
+	int i = 0;
+
+	while (!sourceS->eos()) {
+
+		uint32 chunkType = sourceS->readUint32BE();
+		uint32 chunkSize = sourceS->readUint32BE();
+		
+		if (sourceS->eos())
+			break;
+
+		debug(0, "chunkType = %08X; chunkSize = %d", chunkType, chunkSize);
+
+		if (chunkType == MKID_BE('Rect')) {
+			debug(0, "Rect");
+			sourceS->skip(4);
+			height = sourceS->readUint16BE();
+			width = sourceS->readUint16BE();
+			debug(0, "width = %d; height = %d", width, height);
+		} else if (chunkType == MKID_BE('fMap')) {
+			debug(0, "fMap");
+			lineSize = sourceS->readUint16BE();
+			sourceS->skip(11);
+			cmdFlags = sourceS->readByte();
+			cmdOffs = sourceS->pos();
+			sourceS->skip(chunkSize - 14);
+			debug(0, "lineSize = %d; cmdFlags = %d; cmdOffs = %04X", lineSize, cmdFlags, cmdOffs);
+		} else if (chunkType == MKID_BE('fLCo')) {
+			debug(0, "fLCo");
+			sourceS->skip(9);
+			pixelFlags = sourceS->readByte();
+			pixelOffs = sourceS->pos();
+			sourceS->skip(chunkSize - 10);
+			debug(0, "pixelFlags = %d; pixelOffs = %04X", pixelFlags, pixelOffs);
+		} else if (chunkType == MKID_BE('fPix')) {
+			debug(0, "fPix");
+			sourceS->skip(9);
+			maskFlags = sourceS->readByte();
+			maskOffs = sourceS->pos();
+			sourceS->skip(chunkSize - 10);
+			debug(0, "maskFlags = %d; maskOffs = %04X", maskFlags, maskOffs);
+		} else if (chunkType == MKID_BE('fGCo')) {
+			debug(0, "fGCo");
+			_hasPalette = true;
+			_paletteColorCount = chunkSize / 3;
+			_picturePalette = new byte[_paletteColorCount * 3];
+			sourceS->read(_picturePalette, _paletteColorCount * 3);
+		} else {
+			error("PictureResource::loadChunked() Invalid chunk %08X at %08X", chunkType, sourceS->pos());
+		}
+
+	}
+
+	if (!cmdOffs || !pixelOffs /*|| !maskOffs*/ || !lineSize || !width || !height) {
+		error("PictureResource::loadChunked() Error parsing the picture data, one or more chunks/parameters are missing");
+	}
+
+	_picture = new Graphics::Surface();
+	_picture->create(width, height, 1);
+
+	decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize, cmdFlags, pixelFlags, maskFlags);
+
+	delete sourceS;
+
+}
+
 /* AnimationResource */
 
 AnimationResource::AnimationResource() {
@@ -182,9 +269,14 @@
 void SoundResourceV1::load(byte *source, int size) {
 	// TODO: This is all wrong. Seems like the sound is compressed
 	// but where is the compression info? (chunks, chunk size)
+	
 	_soundSize = size;
 	_soundData = new byte[_soundSize];
-	memcpy(_soundData, source, _soundSize);
+
+	// TODO: We set the audio to silent for now
+	//memcpy(_soundData, source, _soundSize);
+	memset(_soundData, 0x80, _soundSize);
+
 }
 
 /* MenuResource */
@@ -364,6 +456,9 @@
 
 	_resSlots[resType] = new ResourceSlots();
 
+	// Add dummy entry since the resources are 1-based
+	_resSlots[resType]->push_back(ResourceSlot(0, 0));
+
 	for (uint16 i = 0; i < count; i++) {
 		uint32 offset = blockFile->readUint32LE();
 		blockFile->readUint32LE();

Modified: scummvm/trunk/engines/made/resource.h
===================================================================
--- scummvm/trunk/engines/made/resource.h	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/resource.h	2009-01-22 13:04:29 UTC (rev 35997)
@@ -75,6 +75,8 @@
 	byte *_picturePalette;
 	int _paletteColorCount;
 	bool _hasPalette;
+	void loadRaw(byte *source, int size);
+	void loadChunked(byte *source, int size);
 };
 
 class AnimationResource : public Resource {

Modified: scummvm/trunk/engines/made/screen.cpp
===================================================================
--- scummvm/trunk/engines/made/screen.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/screen.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -447,7 +447,6 @@
 		y1 = y;
 		x2 = x + surf->w + 1;
 		y2 = y + surf->h + 1;
-		//TODO: clipRect(x1, y1, x2, y2);
 
 		if (_ground == 0)
 			state |= 2;
@@ -498,7 +497,6 @@
 		y1 = y;
 		x2 = x + anim->getWidth();
 		y2 = y + anim->getHeight();
-		//TODO: clipRect(x1, y1, x2, y2);
 
 		if (anim->getFlags() == 1 || _ground == 0)
 			state |= 2;
@@ -576,7 +574,6 @@
 	y1 = y;
 	x2 = x + textWidth;
 	y2 = y + textHeight;
-	//TODO: clipRect(x1, y1, x2, y2);
 
 	if (textWidth > 0 && outlineColor != -1) {
 		x++;
@@ -610,8 +607,6 @@
 
 void Screen::show() {
 
-	// TODO
-
 	if (_screenLock)
 		return;
 

Modified: scummvm/trunk/engines/made/scriptfuncs.cpp
===================================================================
--- scummvm/trunk/engines/made/scriptfuncs.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/scriptfuncs.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -263,7 +263,6 @@
 		// FIXME: Remove this hack and handle this file properly
 		if (_vm->getGameID() == GID_LGOP2 && musicNum == 2)
 			return 0;
-
 		if (musicNum > 0) {
 			_musicRes = _vm->_res->getMidi(musicNum);
 			if (_musicRes)
@@ -292,7 +291,6 @@
 
 int16 ScriptFunctions::sfSetTextPos(int16 argc, int16 *argv) {
 	// Used in Manhole:NE
-	//warning("Unimplemented opcode: sfSetTextPos");
 	// This seems to be some kind of low-level opcode.
 	// The original engine calls int 10h to set the VGA cursor position.
 	// Since this seems to be used for debugging purposes only it's left out.
@@ -305,25 +303,25 @@
 }
 
 int16 ScriptFunctions::sfPlayNote(int16 argc, int16 *argv) {
-	// TODO: Used in Manhole:NE
+	// TODO: Used in Manhole:NE, Manhole EGA
 	warning("Unimplemented opcode: sfPlayNote");
 	return 0;
 }
 
 int16 ScriptFunctions::sfStopNote(int16 argc, int16 *argv) {
-	// TODO: Used in Manhole:NE
+	// TODO: Used in Manhole:NE, Manhole EGA
 	warning("Unimplemented opcode: sfStopNote");
 	return 0;
 }
 
 int16 ScriptFunctions::sfPlayTele(int16 argc, int16 *argv) {
-	// TODO: Used in Manhole:NE
+	// TODO: Used in Manhole:NE, Manhole EGA
 	warning("Unimplemented opcode: sfPlayTele");
 	return 0;
 }
 
 int16 ScriptFunctions::sfStopTele(int16 argc, int16 *argv) {
-	// TODO: Used in Manhole:NE
+	// TODO: Used in Manhole:NE, Manhole EGA
 	warning("Unimplemented opcode: sfStopTele");
 	return 0;
 }
@@ -618,21 +616,19 @@
 int16 ScriptFunctions::sfGetSoundEnergy(int16 argc, int16 *argv) {
 	// This is called while in-game voices are played to animate 
 	// mouths when NPCs are talking
-
 	int result = 0;
-
-	if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle) && _vm->_soundEnergyArray &&
-		_vm->_soundEnergyIndex < _vm->_soundEnergyArray->size()) {
-		
-		uint32 position = (_vm->_soundRate / 1000) * _vm->_mixer->getSoundElapsedTime(_audioStreamHandle);
-		SoundEnergyItem *soundEnergyItem = &_vm->_soundEnergyArray->operator[](_vm->_soundEnergyIndex);
-
-		result = soundEnergyItem->energy;
-		
-		if (position >= soundEnergyItem->position)
+	if (_vm->_mixer->isSoundHandleActive(_audioStreamHandle) && _vm->_soundEnergyArray) {
+		while (_vm->_soundEnergyIndex < _vm->_soundEnergyArray->size()) {
+			SoundEnergyItem *soundEnergyItem = &_vm->_soundEnergyArray->operator[](_vm->_soundEnergyIndex);
+			if (((_vm->_soundRate / 1000) * _vm->_mixer->getSoundElapsedTime(_audioStreamHandle)) < soundEnergyItem->position) {
+				result = soundEnergyItem->energy;
+				break;
+			}
 			_vm->_soundEnergyIndex++;
+		}
+		if (_vm->_soundEnergyIndex >= _vm->_soundEnergyArray->size())
+			result = 0;
 	}
-
 	return result;
 }
 
@@ -660,9 +656,10 @@
 int16 ScriptFunctions::sfPlayMovie(int16 argc, int16 *argv) {
 	const char *movieName = _vm->_dat->getObjectString(argv[1]);
 	_vm->_system->showMouse(false);
-	_vm->_pmvPlayer->play(movieName);
+	bool completed = _vm->_pmvPlayer->play(movieName);
 	_vm->_system->showMouse(true);
-	return 0;
+	// Return true/false according to if the movie was canceled or not
+	return completed ? -1 : 0;
 }
 
 int16 ScriptFunctions::sfLoadSound(int16 argc, int16 *argv) {

Modified: scummvm/trunk/engines/made/sound.cpp
===================================================================
--- scummvm/trunk/engines/made/sound.cpp	2009-01-22 06:41:57 UTC (rev 35996)
+++ scummvm/trunk/engines/made/sound.cpp	2009-01-22 13:04:29 UTC (rev 35997)
@@ -70,6 +70,8 @@
 
 		workSample = prevSample;
 
+		soundEnergyItem.position += chunkSize;
+
 		switch (type) {
 
 		case 0:
@@ -77,10 +79,6 @@
 			workSample = 0;
 
 			soundEnergyItem.energy = 0;
-			// FIXME: I believe that this should be added in a different manner than the
-			// rest of the values. 0 means "mouth shut", but it seems to be occuring too
-			// often. Removing this bit makes the mouth of the lighthouse keeper move
-			// without going too much off-sync. If I'm wrong here, please remove this.
 			if (soundEnergyArray)
 				soundEnergyArray->push_back(soundEnergyItem);
 
@@ -121,7 +119,7 @@
 				soundBuffer[i] = *source++;
 			workSample = soundBuffer[workChunkSize - 1] - 128;
 			
-			soundEnergyItem.energy = type - 1;
+			soundEnergyItem.energy = 4;
 			if (soundEnergyArray)
 				soundEnergyArray->push_back(soundEnergyItem);
 			
@@ -155,7 +153,6 @@
 		prevSample = workSample;
 		memcpy(dest, soundBuffer, chunkSize);
 		dest += chunkSize;
-		soundEnergyItem.position += chunkSize;
 
 	}
 


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