[Scummvm-cvs-logs] SF.net SVN: scummvm:[40488] scummvm/trunk/engines/kyra

lordhoto at users.sourceforge.net lordhoto at users.sourceforge.net
Tue May 12 16:18:08 CEST 2009


Revision: 40488
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40488&view=rev
Author:   lordhoto
Date:     2009-05-12 14:18:08 +0000 (Tue, 12 May 2009)

Log Message:
-----------
Change script file loading code to use Common::IFFParser instead of a self written IFF reader.

Modified Paths:
--------------
    scummvm/trunk/engines/kyra/script.cpp
    scummvm/trunk/engines/kyra/script.h
    scummvm/trunk/engines/kyra/script_tim.cpp

Modified: scummvm/trunk/engines/kyra/script.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script.cpp	2009-05-12 13:56:09 UTC (rev 40487)
+++ scummvm/trunk/engines/kyra/script.cpp	2009-05-12 14:18:08 UTC (rev 40488)
@@ -28,6 +28,7 @@
 #include "common/stream.h"
 #include "common/util.h"
 #include "common/system.h"
+
 #include "kyra/kyra_v1.h"
 #include "kyra/resource.h"
 #include "kyra/script.h"
@@ -66,69 +67,62 @@
 }
 
 bool EMCInterpreter::load(const char *filename, EMCData *scriptData, const Common::Array<const Opcode*> *opcodes) {
-	IFFParser file(filename, _vm->resource());
-	if (!file) {
+	Common::SeekableReadStream *stream = _vm->resource()->createReadStream(filename);
+	if (!stream) {
 		error("Couldn't open script file '%s'", filename);
 		return false;
 	}
 
 	memset(scriptData, 0, sizeof(EMCData));
 
-	uint32 formBlockSize = file.getFORMBlockSize();
-	if (formBlockSize == (uint32)-1) {
-		error("No FORM chunk found in file: '%s'", filename);
-		return false;
-	}
+	IFFParser iff(*stream);
+	Common::IFFChunk *chunk = 0;
 
-	uint32 chunkSize = file.getBlockSize(TEXT_CHUNK);
-	if (chunkSize != (uint32)-1) {
-		scriptData->text = new byte[chunkSize];
+	while ((chunk = iff.nextChunk()) != 0) {
+		switch (chunk->id) {
+		case MKID_BE('TEXT'):
+			scriptData->text = new byte[chunk->size];
+			assert(scriptData->text);
+			chunk->read(scriptData->text, chunk->size);
+			break;
 
-		if (!file.loadBlock(TEXT_CHUNK, scriptData->text, chunkSize)) {
-			unload(scriptData);
-			error("Couldn't load TEXT chunk from file: '%s'", filename);
-			return false;
-		}
-	}
+		case MKID_BE('ORDR'):
+			scriptData->ordr = new uint16[chunk->size >> 1];
+			assert(scriptData->ordr);
+			chunk->read(scriptData->ordr, chunk->size);
 
-	chunkSize = file.getBlockSize(ORDR_CHUNK);
-	if (chunkSize == (uint32)-1) {
-		unload(scriptData);
-		error("No ORDR chunk found in file: '%s'", filename);
-		return false;
-	}
-	chunkSize >>= 1;
+			for (int i = (chunk->size >> 1) - 1; i >= 0; --i)
+				scriptData->ordr[i] = READ_BE_UINT16(&scriptData->ordr[i]);
+			break;
 
-	scriptData->ordr = new uint16[chunkSize];
+		case MKID_BE('DATA'):
+			scriptData->data = new uint16[chunk->size >> 1];
+			assert(scriptData->data);
+			chunk->read(scriptData->data, chunk->size);
 
-	if (!file.loadBlock(ORDR_CHUNK, scriptData->ordr, chunkSize << 1)) {
-		unload(scriptData);
-		error("Couldn't load ORDR chunk from file: '%s'", filename);
-		return false;
+			for (int i = (chunk->size >> 1) - 1; i >= 0; --i)
+				scriptData->data[i] = READ_BE_UINT16(&scriptData->data[i]);
+			break;
+
+		default:
+			warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename);
+			break;
+		}
 	}
 
-	while (chunkSize--)
-		scriptData->ordr[chunkSize] = READ_BE_UINT16(&scriptData->ordr[chunkSize]);
-
-	chunkSize = file.getBlockSize(DATA_CHUNK);
-	if (chunkSize == (uint32)-1) {
+	if (!scriptData->ordr) {
 		unload(scriptData);
-		error("No DATA chunk found in file: '%s'", filename);
+		error("Couldn't read ORDR chunk from file: '%s'", filename);
 		return false;
 	}
-	chunkSize >>= 1;
 
-	scriptData->data = new uint16[chunkSize];
-
-	if (!file.loadBlock(DATA_CHUNK, scriptData->data, chunkSize << 1)) {
+	if (!scriptData->data) {
 		unload(scriptData);
-		error("Couldn't load DATA chunk from file: '%s'", filename);
+		error("Couldn't read DATA chunk from file: '%s'", filename);
 		return false;
 	}
-	scriptData->dataSize = chunkSize;
 
-	while (chunkSize--)
-		scriptData->data[chunkSize] = READ_BE_UINT16(&scriptData->data[chunkSize]);
+	delete stream;
 
 	scriptData->sysFuncs = opcodes;
 
@@ -218,83 +212,6 @@
 }
 
 #pragma mark -
-#pragma mark - IFFParser implementation
-#pragma mark -
-
-void IFFParser::setFile(const char *filename, Resource *res) {
-	destroy();
-
-	res->exists(filename, true);
-	_stream = res->createReadStream(filename);
-	assert(_stream);
-	_startOffset = 0;
-	_endOffset = _stream->size();
-}
-
-void IFFParser::destroy() {
-	delete _stream;
-	_stream = 0;
-	_startOffset = _endOffset = 0;
-}
-
-uint32 IFFParser::getFORMBlockSize() {
-	uint32 oldOffset = _stream->pos();
-
-	uint32 data = _stream->readUint32LE();
-
-	if (data != FORM_CHUNK) {
-		_stream->seek(oldOffset);
-		return (uint32)-1;
-	}
-
-	data = _stream->readUint32BE();
-	return data;
-}
-
-uint32 IFFParser::getBlockSize(const uint32 chunkName) {
-	uint32 size = (uint32)-1;
-
-	_stream->seek(_startOffset + 0x0C);
-
-	while ((uint)_stream->pos() < _endOffset) {
-		uint32 chunk = _stream->readUint32LE();
-		uint32 size_temp = _stream->readUint32BE();
-
-		if (chunk != chunkName) {
-			_stream->seek((size_temp + 1) & (~1), SEEK_CUR);
-			assert((uint)_stream->pos() <= _endOffset);
-		} else {
-			size = size_temp;
-			break;
-		}
-	}
-
-	return size;
-}
-
-bool IFFParser::loadBlock(const uint32 chunkName, void *loadTo, uint32 ptrSize) {
-	_stream->seek(_startOffset + 0x0C);
-
-	while ((uint)_stream->pos() < _endOffset) {
-		uint32 chunk = _stream->readUint32LE();
-		uint32 chunkSize = _stream->readUint32BE();
-
-		if (chunk != chunkName) {
-			_stream->seek((chunkSize + 1) & (~1), SEEK_CUR);
-			assert((uint)_stream->pos() <= _endOffset);
-		} else {
-			uint32 loadSize = 0;
-
-			loadSize = MIN(ptrSize, chunkSize);
-			_stream->read(loadTo, loadSize);
-			return true;
-		}
-	}
-
-	return false;
-}
-
-#pragma mark -
 #pragma mark - Command implementations
 #pragma mark -
 

Modified: scummvm/trunk/engines/kyra/script.h
===================================================================
--- scummvm/trunk/engines/kyra/script.h	2009-05-12 13:56:09 UTC (rev 40487)
+++ scummvm/trunk/engines/kyra/script.h	2009-05-12 14:18:08 UTC (rev 40488)
@@ -29,6 +29,7 @@
 #include "common/stream.h"
 #include "common/array.h"
 #include "common/func.h"
+#include "common/iff_container.h"
 
 namespace Kyra {
 
@@ -64,34 +65,28 @@
 #define stackPos(x) (script->stack[script->sp+x])
 #define stackPosString(x) ((const char*)&script->dataPtr->text[READ_BE_UINT16(&script->dataPtr->text[stackPos(x)<<1])])
 
-#define FORM_CHUNK 0x4D524F46
-#define TEXT_CHUNK 0x54584554
-#define DATA_CHUNK 0x41544144
-#define ORDR_CHUNK 0x5244524F
-#define AVTL_CHUNK 0x4C545641
-
 class Resource;
 class KyraEngine_v1;
 
-class IFFParser {
+class IFFParser : public Common::IFFParser {
 public:
-	IFFParser() : _stream(0), _startOffset(0), _endOffset(0) {}
-	IFFParser(const char *filename, Resource *res) : _stream(0), _startOffset(0), _endOffset(0) { setFile(filename, res); }
-	~IFFParser() { destroy(); }
-
-	void setFile(const char *filename, Resource *res);
-
-	operator bool() const { return (_startOffset != _endOffset) && _stream; }
-
-	uint32 getFORMBlockSize();
-	uint32 getBlockSize(const uint32 chunk);
-	bool loadBlock(const uint32 chunk, void *loadTo, uint32 ptrSize);
-private:
-	void destroy();
-
-	Common::SeekableReadStream *_stream;
-	uint32 _startOffset;
-	uint32 _endOffset;
+	IFFParser(Common::SeekableReadStream &input) : Common::IFFParser(input) {
+		// It seems Westwood missunderstood the 'size' field of the FORM chunk.
+		//
+		// For EMC scripts (type EMC2) it's filesize instead of filesize - 8,
+		// means accidently including the 8 bytes used by the chunk header for the FORM
+		// chunk.
+		//
+		// For TIM scripts (type AVFS) it's filesize - 12 instead of filesize - 8,
+		// means it will not include the size of the 'type' field in the FORM chunk,
+		// instead of only not including the chunk header size.
+		//
+		// Both lead to some problems in our IFF parser, either reading after the end
+		// of file or producing a "Chunk overread" error message. To work around this
+		// we need to adjust the size field properly.
+		if (_typeId == MKID_BE('EMC2') || _typeId == MKID_BE('AVFS'))
+			_formChunk.size = input.size() - 8;
+	}
 };
 
 class EMCInterpreter {

Modified: scummvm/trunk/engines/kyra/script_tim.cpp
===================================================================
--- scummvm/trunk/engines/kyra/script_tim.cpp	2009-05-12 13:56:09 UTC (rev 40487)
+++ scummvm/trunk/engines/kyra/script_tim.cpp	2009-05-12 14:18:08 UTC (rev 40488)
@@ -34,6 +34,7 @@
 #include "kyra/screen_lol.h"
 #endif // ENABLE_LOL
 
+#include "common/iff_container.h"
 #include "common/endian.h"
 
 namespace Kyra {
@@ -87,7 +88,7 @@
 #undef COMMAND_UNIMPL
 #undef COMMAND
 
-	_commands = commandProcs ;
+	_commands = commandProcs;
 	_commandsSize = ARRAYSIZE(commandProcs);
 
 	_animations = new Animation[TIM::kWSASlots];
@@ -115,21 +116,17 @@
 	delete[] _animations;	
 }
 
-TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode*> *opcodes) {
+TIM *TIMInterpreter::load(const char *filename, const Common::Array<const TIMOpcode *> *opcodes) {
 	if (!vm()->resource()->exists(filename))
 		return 0;
 
-	IFFParser file(filename, vm()->resource());
-	if (!file)
+	Common::SeekableReadStream *stream = vm()->resource()->createReadStream(filename);
+	if (!stream)
 		error("Couldn't open TIM file '%s'", filename);
 
-	uint32 formBlockSize = file.getFORMBlockSize();
-	if (formBlockSize == 0xFFFFFFFF)
-		error("No FORM chunk found in TIM file '%s'", filename);
-
-	if (formBlockSize < 20)
-		error("TIM file '%s' FORM chunk size smaller than 20", filename);
-
+	IFFParser iff(*stream);
+	Common::IFFChunk *chunk = 0;
+	
 	TIM *tim = new TIM;
 	assert(tim);
 	memset(tim, 0, sizeof(TIM));
@@ -137,27 +134,44 @@
 	tim->procFunc = -1;
 	tim->opcodes = opcodes;
 
-	uint32 avtlChunkSize = file.getBlockSize(AVTL_CHUNK);
-	uint32 textChunkSize = file.getBlockSize(TEXT_CHUNK);
+	int avtlChunkSize = 0;
 
-	tim->avtl = new uint16[avtlChunkSize/2];
-	if (textChunkSize != 0xFFFFFFFF)
-		tim->text = new byte[textChunkSize];
+	while ((chunk = iff.nextChunk()) != 0) {
+		switch (chunk->id) {
+		case MKID_BE('TEXT'):
+			tim->text = new byte[chunk->size];
+			assert(tim->text);
+			if (chunk->read(tim->text, chunk->size) != chunk->size)
+				error("Couldn't read TEXT chunk from file '%s'", filename);
+			break;
 
-	if (!file.loadBlock(AVTL_CHUNK, tim->avtl, avtlChunkSize))
-		error("Couldn't read AVTL chunk in TIM file '%s'", filename);
-	if (textChunkSize != 0xFFFFFFFF && !file.loadBlock(TEXT_CHUNK, tim->text, textChunkSize))
-		error("Couldn't read TEXT chunk in TIM file '%s'", filename);
+		case MKID_BE('AVTL'):
+			avtlChunkSize = chunk->size >> 1;
+			tim->avtl = new uint16[avtlChunkSize];
+			assert(tim->avtl);
+			chunk->read(tim->avtl, chunk->size);
 
-	avtlChunkSize >>= 1;
-	for (uint i = 0; i < avtlChunkSize; ++i)
-		tim->avtl[i] = READ_LE_UINT16(tim->avtl + i);
+			for (int i = avtlChunkSize - 1; i >= 0; --i)
+				tim->avtl[i] = READ_LE_UINT16(&tim->avtl[i]);
+			break;
 
+		default:
+			warning("Unexpected chunk '%s' of size %d found in file '%s'", Common::ID2string(chunk->id), chunk->size, filename);
+			break;
+		}
+	}
+
+	delete stream;
+
+	if (!tim->avtl)
+		error("Couldn't read AVTL chunk from file: '%s'", filename);
+
 	int num = (avtlChunkSize < TIM::kCountFuncs) ? avtlChunkSize : (int)TIM::kCountFuncs;
 	for (int i = 0; i < num; ++i)
 		tim->func[i].avtl = tim->avtl + tim->avtl[i];
 
 	strncpy(tim->filename, filename, 13);
+	tim->filename[12] = 0;
 
 	return tim;
 }


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