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

thebluegr at users.sourceforge.net thebluegr at users.sourceforge.net
Wed Jun 2 15:17:36 CEST 2010


Revision: 49391
          http://scummvm.svn.sourceforge.net/scummvm/?rev=49391&view=rev
Author:   thebluegr
Date:     2010-06-02 13:17:36 +0000 (Wed, 02 Jun 2010)

Log Message:
-----------
- Fixed findGameObject() to properly handle SCI0-SCI1 games where the first block of script 0 isn't the exports block
- Changed many places where Common::File is used directly to use Common::SeekableReadStream instead (in order to ultimately remove the SCI_detection hack in the fallback detector)

Modified Paths:
--------------
    scummvm/trunk/engines/sci/resource.cpp
    scummvm/trunk/engines/sci/resource.h
    scummvm/trunk/engines/sci/resource_audio.cpp

Modified: scummvm/trunk/engines/sci/resource.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource.cpp	2010-06-02 04:45:44 UTC (rev 49390)
+++ scummvm/trunk/engines/sci/resource.cpp	2010-06-02 13:17:36 UTC (rev 49391)
@@ -237,6 +237,7 @@
 	ResourceSource *newsrc = new ResourceSource();
 
 	newsrc->source_type = kSourceDirectory;
+	newsrc->resourceFile = 0;
 	newsrc->scanned = false;
 	newsrc->location_name = dirname;
 
@@ -257,7 +258,7 @@
 
 // Resource manager constructors and operations
 
-bool ResourceManager::loadPatch(Resource *res, Common::File &file) {
+bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) {
 	// We assume that the resource type matches res->type
 	//  We also assume that the current file position is right at the actual data (behind resourceid/headersize byte)
 
@@ -272,12 +273,12 @@
 
 	unsigned int really_read;
 	if (res->_headerSize > 0) {
-		really_read = file.read(res->_header, res->_headerSize);
+		really_read = file->read(res->_header, res->_headerSize);
 		if (really_read != res->_headerSize)
 			error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->_headerSize);
 	}
 
-	really_read = file.read(res->data, res->size);
+	really_read = file->read(res->data, res->size);
 	if (really_read != res->size)
 		error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size);
 
@@ -295,7 +296,7 @@
 	}
 	// Skip resourceid and header size byte
 	file.seek(2, SEEK_SET);
-	return loadPatch(res, file);
+	return loadPatch(res, &file);
 }
 
 Common::File *ResourceManager::getVolumeFile(const char *filename) {
@@ -352,10 +353,15 @@
 		return;
 	}
 
-	Common::File *file;
+	Common::SeekableReadStream *fileStream;
+
 	// Either loading from volume or patch loading failed
-	file = getVolumeFile(res->_source->location_name.c_str());
-	if (!file) {
+	if (res->_source->resourceFile)
+		fileStream = res->_source->resourceFile->createReadStream();
+	else
+		fileStream = getVolumeFile(res->_source->location_name.c_str());
+
+	if (!fileStream) {
 		warning("Failed to open %s", res->_source->location_name.c_str());
 		res->unalloc();
 		return;
@@ -363,8 +369,8 @@
 
 	switch(res->_source->source_type) {
 	case kSourceWave:
-		file->seek(res->_fileOffset, SEEK_SET);
-		loadFromWaveFile(res, *file);
+		fileStream->seek(res->_fileOffset, SEEK_SET);
+		loadFromWaveFile(res, fileStream);
 		return;
 
 	case kSourceAudioVolume:
@@ -395,30 +401,30 @@
 
 			if (!compressedOffset)
 				error("could not translate offset to compressed offset in audio volume");
-			file->seek(compressedOffset, SEEK_SET);
+			fileStream->seek(compressedOffset, SEEK_SET);
 
 			switch (res->_id.type) {
 			case kResourceTypeAudio:
 			case kResourceTypeAudio36:
 				// Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1
-				loadFromAudioVolumeSCI1(res, *file);
+				loadFromAudioVolumeSCI1(res, fileStream);
 				return;
 			default:
 				break;
 			}
 		} else {
 			// original file, directly seek to given offset and get SCI1/SCI1.1 audio resource
-			file->seek(res->_fileOffset, SEEK_SET);
+			fileStream->seek(res->_fileOffset, SEEK_SET);
 		}
 		if (getSciVersion() < SCI_VERSION_1_1)
-			loadFromAudioVolumeSCI1(res, *file);
+			loadFromAudioVolumeSCI1(res, fileStream);
 		else
-			loadFromAudioVolumeSCI11(res, *file);
+			loadFromAudioVolumeSCI11(res, fileStream);
 		return;
 
 	default:
-		file->seek(res->_fileOffset, SEEK_SET);
-		int error = decompress(res, file);
+		fileStream->seek(res->_fileOffset, SEEK_SET);
+		int error = decompress(res, fileStream);
 		if (error) {
 			warning("Error %d occured while reading %s from resource file: %s",
 				    error, res->_id.toString().c_str(), sci_error_types[error]);
@@ -872,7 +878,6 @@
 
 ResourceManager::ResVersion ResourceManager::detectMapVersion() {
 	Common::SeekableReadStream *fileStream = 0;
-	Common::File *file = 0;
 	byte buff[6];
 	ResourceSource *rsrc= 0;
 
@@ -883,7 +888,7 @@
 			if (rsrc->resourceFile) {
 				fileStream = rsrc->resourceFile->createReadStream();
 			} else {
-				file = new Common::File();
+				Common::File *file = new Common::File();
 				file->open(rsrc->location_name);
 				if (file->isOpen())
 					fileStream = file;
@@ -963,7 +968,6 @@
 
 ResourceManager::ResVersion ResourceManager::detectVolVersion() {
 	Common::SeekableReadStream *fileStream = 0;
-	Common::File *file = 0;
 	ResourceSource *rsrc;
 
 	for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) {
@@ -973,7 +977,7 @@
 			if (rsrc->resourceFile) {
 				fileStream = rsrc->resourceFile->createReadStream();
 			} else {
-				file = new Common::File();
+				Common::File *file = new Common::File();
 				file->open(rsrc->location_name);
 				if (file->isOpen())
 					fileStream = file;
@@ -1063,7 +1067,7 @@
 
 // version-agnostic patch application
 void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, int resnumber) {
-	Common::File file;
+	Common::SeekableReadStream *fileStream = 0;
 	Resource *newrsc;
 	ResourceId resId = ResourceId(restype, resnumber);
 	byte patchtype, patch_data_offset;
@@ -1071,19 +1075,28 @@
 
 	if (resnumber == -1)
 		return;
-	if (!file.open(source->location_name)) {
-		warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str());
-		return;
+
+	if (source->resourceFile) {
+		fileStream = source->resourceFile->createReadStream();
+	} else {
+		Common::File *file = new Common::File();
+		if (!file->open(source->location_name)) {
+			warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str());
+			return;
+		}
+		fileStream = file;
 	}
-	fsize = file.size();
+	fsize = fileStream->size();
 	if (fsize < 3) {
 		debug("Patching %s failed - file too small", source->location_name.c_str());
 		return;
 	}
 
-	patchtype = file.readByte() & 0x7F;
-	patch_data_offset = file.readByte();
+	patchtype = fileStream->readByte() & 0x7F;
+	patch_data_offset = fileStream->readByte();
 
+	delete fileStream;
+
 	if (patchtype != restype) {
 		debug("Patching %s failed - resource type mismatch", source->location_name.c_str());
 	}
@@ -1097,8 +1110,12 @@
 			case 1:
 				patch_data_offset = 2;
 				break;
+			case 4:
+				patch_data_offset = 8;
+				break;
 			default:
-				warning("Resource patch unsupported special case %X", patch_data_offset);
+				warning("Resource patch unsupported special case %X", patch_data_offset & 0x7F);
+				return;
 		}
 	}
 
@@ -1180,6 +1197,7 @@
 				psrcPatch = new ResourceSource;
 				psrcPatch->source_type = kSourcePatch;
 				psrcPatch->location_name = name;
+				psrcPatch->resourceFile = 0;
 				processPatch(psrcPatch, (ResourceType)i, number);
 			}
 		}
@@ -1931,19 +1949,58 @@
 	return offset == res->size;
 }
 
-#define READ_UINT16(ptr) (!isSci11Mac() ? READ_LE_UINT16(ptr) : READ_BE_UINT16(ptr))
+// Same function as Script::findBlock(). Slight code
+// duplication here, but this has been done to keep the resource
+// manager independent from the rest of the engine
+static byte *findSci0ExportsBlock(byte *buffer) {
+	byte *buf = buffer;
+	bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
 
+	if (oldScriptHeader)
+		buf += 2;
+
+	do {
+		int seekerType = READ_LE_UINT16(buf);
+
+		if (seekerType == 0)
+			break;
+		if (seekerType == 7)	// exports
+			return buf;
+
+		int seekerSize = READ_LE_UINT16(buf + 2);
+		assert(seekerSize > 0);
+		buf += seekerSize;
+	} while (1);
+
+	return NULL;
+}
+
 reg_t ResourceManager::findGameObject(bool addSci11ScriptOffset) {
 	Resource *script = findResource(ResourceId(kResourceTypeScript, 0), false);
 
 	if (!script)
 		return NULL_REG;
 
-	int extraBytes = 0;
-	if (getSciVersion() == SCI_VERSION_0_EARLY || getSciVersion() >= SCI_VERSION_1_1)
-		extraBytes = 2;
+	byte *offsetPtr = 0;
+
+	if (getSciVersion() < SCI_VERSION_1_1) {
+		byte *buf = (getSciVersion() == SCI_VERSION_0_EARLY) ? script->data + 2 : script->data;
+
+		// Check if the first block is the exports block (in most cases, it is)
+		bool exportsIsFirst = (READ_LE_UINT16(buf + 4) == 7);
+		if (exportsIsFirst) {
+			offsetPtr = buf + 4 + 2;
+		} else {
+			offsetPtr = findSci0ExportsBlock(script->data);
+			if (!offsetPtr)
+				error("Unable to find exports block from script 0");
+			offsetPtr += 4 + 2;
+		}
+	} else {
+		offsetPtr = script->data + 4 + 2 + 2;
+	}
 	
-	int16 offset = READ_UINT16(script->data + extraBytes + 4 + 2);
+	int16 offset = !isSci11Mac() ? READ_LE_UINT16(offsetPtr) : READ_BE_UINT16(offsetPtr);
 
 	// In SCI1.1 and newer, the heap is appended at the end of the script,
 	// so adjust the offset accordingly
@@ -1986,6 +2043,4 @@
 	return sierraId;
 }
 
-#undef READ_UINT16
-
 } // End of namespace Sci

Modified: scummvm/trunk/engines/sci/resource.h
===================================================================
--- scummvm/trunk/engines/sci/resource.h	2010-06-02 04:45:44 UTC (rev 49390)
+++ scummvm/trunk/engines/sci/resource.h	2010-06-02 13:17:36 UTC (rev 49391)
@@ -395,11 +395,11 @@
 
 	Common::File *getVolumeFile(const char *filename);
 	void loadResource(Resource *res);
-	bool loadPatch(Resource *res, Common::File &file);
+	bool loadPatch(Resource *res, Common::SeekableReadStream *file);
 	bool loadFromPatchFile(Resource *res);
-	bool loadFromWaveFile(Resource *res, Common::File &file);
-	bool loadFromAudioVolumeSCI1(Resource *res, Common::File &file);
-	bool loadFromAudioVolumeSCI11(Resource *res, Common::File &file);
+	bool loadFromWaveFile(Resource *res, Common::SeekableReadStream *file);
+	bool loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file);
+	bool loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file);
 	void freeOldResources();
 	int decompress(Resource *res, Common::SeekableReadStream *file);
 	int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression);

Modified: scummvm/trunk/engines/sci/resource_audio.cpp
===================================================================
--- scummvm/trunk/engines/sci/resource_audio.cpp	2010-06-02 04:45:44 UTC (rev 49390)
+++ scummvm/trunk/engines/sci/resource_audio.cpp	2010-06-02 13:17:36 UTC (rev 49391)
@@ -62,10 +62,10 @@
 	}
 }
 
-bool ResourceManager::loadFromWaveFile(Resource *res, Common::File &file) {
+bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream *file) {
 	res->data = new byte[res->size];
 
-	uint32 really_read = file.read(res->data, res->size);
+	uint32 really_read = file->read(res->data, res->size);
 	if (really_read != res->size)
 		error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size);
 
@@ -73,26 +73,26 @@
 	return true;
 }
 
-bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::File &file) {
+bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file) {
 	// Check for WAVE files here
-	uint32 riffTag = file.readUint32BE();
+	uint32 riffTag = file->readUint32BE();
 	if (riffTag == MKID_BE('RIFF')) {
 		res->_headerSize = 0;
-		res->size = file.readUint32LE();
-		file.seek(-8, SEEK_CUR);
+		res->size = file->readUint32LE();
+		file->seek(-8, SEEK_CUR);
 		return loadFromWaveFile(res, file);
 	}
-	file.seek(-4, SEEK_CUR);
+	file->seek(-4, SEEK_CUR);
 
-	ResourceType type = (ResourceType)(file.readByte() & 0x7f);
+	ResourceType type = (ResourceType)(file->readByte() & 0x7f);
 	if (((res->_id.type == kResourceTypeAudio || res->_id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio))
 		|| ((res->_id.type == kResourceTypeSync || res->_id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) {
-		warning("Resource type mismatch loading %s from %s", res->_id.toString().c_str(), file.getName());
+		warning("Resource type mismatch loading %s", res->_id.toString().c_str());
 		res->unalloc();
 		return false;
 	}
 
-	res->_headerSize = file.readByte();
+	res->_headerSize = file->readByte();
 
 	if (type == kResourceTypeAudio) {
 		if (res->_headerSize != 11 && res->_headerSize != 12) {
@@ -102,23 +102,23 @@
 		}
 
 		// Load sample size
-		file.seek(7, SEEK_CUR);
-		res->size = file.readUint32LE();
+		file->seek(7, SEEK_CUR);
+		res->size = file->readUint32LE();
 		// Adjust offset to point at the header data again
-		file.seek(-11, SEEK_CUR);
+		file->seek(-11, SEEK_CUR);
 	}
 
 	return loadPatch(res, file);
 }
 
-bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::File &file) {
+bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file) {
 	res->data = new byte[res->size];
 
 	if (res->data == NULL) {
 		error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str());
 	}
 
-	unsigned int really_read = file.read(res->data, res->size);
+	unsigned int really_read = file->read(res->data, res->size);
 	if (really_read != res->size)
 		warning("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->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